Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Getting ActiveRecord::HstoreTypeMismatch with valid Hash. #57

Open
Tonkpils opened this Issue · 8 comments

8 participants

@Tonkpils

I just started using this gem along with Rails 3.2.9. I'm trying to get it to work the accessor methods. I'm not sure if it's an issue with Rails or with this gem but here's the issue.

I installed the Gem, ran the setup I added the serialize statement to my model. I also added the store_accessor to my column like so:

class App < ActiveRecord::Base
  serialize :properties, ActiveRecord::Coders::Hstore

  store_accessor :properties, [:author]
  ...
end

In the rails console I ran the following:

1.9.3p327 :001 > a = App.first
  App Load (3.1ms)  SELECT "apps".* FROM "apps" LIMIT 1
 => #<App id: 1, name: "Some Name", properties: {"author"=>"Leo", "version"=>"1.0"}> 
1.9.3p327 :002 > a.author
 => nil 
1.9.3p327 :003 > a.author = "Chuck"
 => "Chuck" 
1.9.3p327 :004 > a.save!
   (0.5ms)  BEGIN
  App Exists (0.9ms)  SELECT 1 AS one FROM "apps" WHERE ("apps"."name" = 'Some Name' AND "apps"."id" != 1) LIMIT 1
   (0.6ms)  UPDATE "apps" SET "properties" = 'author=>Leo,version=>1.0,author=>Chuck', "updated_at" = '2012-12-06 23:10:18.689675' WHERE "apps"."id" = 1
   (0.5ms)  COMMIT
 => true 
1.9.3p327 :005 > a.author
 => nil 
1.9.3p327 :006 > a
 => #<App id: 1, name: "Some Name", properties: {"author"=>"Chuck", "version"=>"1.0"}> 

So the attribute is updating but I can't access the getter for the attribute.

Now I was researching this issue a bit and found that Rails has a store method that does the serializing but instead of using ActiveRecord::Coders::Hstore, it uses Hash. I tried using said method and the whole thing breaks when trying to save.

This is the code in store method for Rails

store.rb

module ClassMethods
  def store(store_attribute, options = {})
    serialize store_attribute, Hash
    store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
  end

  def store_accessor(store_attribute, *keys)
    Array(keys).flatten.each do |key|
      define_method("#{key}=") do |value|
        send("#{store_attribute}=", {}) unless send(store_attribute).is_a?(Hash)
        send(store_attribute)[key] = value
        send("#{store_attribute}_will_change!")
      end

      define_method(key) do
        send("#{store_attribute}=", {}) unless send(store_attribute).is_a?(Hash)
        send(store_attribute)[key]
      end
    end
  end
end

I get the following in the Rails console:

Loading development environment (Rails 3.2.9)
1.9.3p327 :001 > a = App.first
  App Load (3.1ms)  SELECT "apps".* FROM "apps" LIMIT 1
 => #<App id: 1, name: "Some Name", properties: "\"author\"=>\"Leo\", \"version\"=>\"1.0\""> 
1.9.3p327 :002 > a.author
 => nil 
1.9.3p327 :003 > a.author = "Chuck"
 => "Chuck" 
1.9.3p327 :004 > a.save!
   (0.4ms)  BEGIN
  App Exists (0.8ms)  SELECT 1 AS one FROM "apps" WHERE ("apps"."name" = 'Some Name' AND "apps"."id" != 1) LIMIT 1
   (0.3ms)  ROLLBACK
ActiveRecord::HstoreTypeMismatch: properties must have a Hash or a valid hstore value (---
:author: Chuck
)
    from /Users/leo/.rvm/gems/ruby-1.9.3-p327@developer/gems/activerecord-postgres-hstore-0.4.1/lib/activerecord-postgres-hstore/activerecord.rb:159:in `quote_with_hstore'
...

Important

Notice that I reloaded the rails console from the run before I switched to using the store method. The value of author in properties was changed back to "Leo" instead of "Chuck"

I also happened to find a quick fix for the getter on the first option ( the one using serialize from ActiveRecord::Coders)

I modified the line in store.rb that has

send(store_attribute)[key] to => send(store_attribute)["#{key}"]

and I was able to access the attributes. Still it didn't update after saving the model leaving and starting the console back.

Any insight on this?

@nateberkopec

Hm, this gem definitely seems incompatible with store_accessor - I'm getting the same issue.

@anthonator

Looking around I'm seeing workarounds but it seems to make sense to bake this in.

https://gist.github.com/2834785

@Tonkpils

:thumbsup: I actually ended up using that. Although, I later realized that in my use case it wasn't necessary to have accessors for the attributes and I just needed to iterate through all the dynamic attributes in the hstore and display them. There still might be that use case where the accessors in the hstore attributes might come in handy.

@diogob diogob closed this
@diogob diogob closed this
@jsmestad

Any official word on placing this workaround in the gem itself?

@diogob
Owner

I'll take a look ASAP

@diogob diogob reopened this
@masterkain

Watching this :+1:

@b-murphy

+1

@jatap

+1
:+1:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.