Hstore和Rails

我正在尝试使用最新版本的activerecord-postgres-hstore gem在Rails 3.2.9项目中使用Hstore,并且我在使用ActiveRecord提供的store_accessor获取Hstore中的值时遇到了一些麻烦。

我的模型看起来像这样:

class Person < ActiveRecord::Base serialize :data, ActiveRecord::Coders::Hstore attr_accessible :data, :name store_accessor :data, :age, :gender end 

当我进入rails控制台时,我得到的是:

 Loading development environment (Rails 3.2.9) 1.9.3-p327 :001 > p = Person.find(3) Person Load (9.8ms) SELECT "people".* FROM "people" WHERE "people"."id" = $1 LIMIT 1 [["id", 3]] => #"34", "gender"=>"male"}, created_at: "2012-12-07 15:01:53", updated_at: "2012-12-07 15:27:40"> 1.9.3-p327 :002 > p.age => nil 1.9.3-p327 :003 > p.age = "204" => "204" 1.9.3-p327 :004 > p.save! (0.2ms) BEGIN (0.6ms) UPDATE "people" SET "data" = 'age=>34,gender=>male,age=>204', "updated_at" = '2012-12-07 15:28:33.097404' WHERE "people"."id" = 3 (2.2ms) COMMIT => true 1.9.3-p327 :005 > p => #"204", "gender"=>"male"}, created_at: "2012-12-07 15:01:53", updated_at: "2012-12-07 15:28:33"> 1.9.3-p327 :006 > exit % rails c 12-12-07 - 10:28:35 Loading development environment (Rails 3.2.9) 1.9.3-p327 :001 > p = Person.find(3) Person Load (6.9ms) SELECT "people".* FROM "people" WHERE "people"."id" = $1 LIMIT 1 [["id", 3]] => #"34", "gender"=>"male"}, created_at: "2012-12-07 15:01:53", updated_at: "2012-12-07 15:28:33"> 

请注意保存! 确实更新了这个人。 当我退出控制台并返回记录时返回到原始数据集。

另外,请注意,当我尝试访问age它返回nil。

如果有人想知道这是store_accessor方法在ActiveRecord中的作用

store.rb

 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 

当我在它运行的控制台中执行相同的send(store_attribute)[key]行时,这非常奇怪:

 1.9.3-p327 :010 > p.send(:data)['age'] => "34" 1.9.3-p327 :011 > p.send(:data)['age'] = "500" => "500" 1.9.3-p327 :012 > p.send("data_will_change!") => {"age"=>"500", "gender"=>"male"} 1.9.3-p327 :013 > p.save! (0.2ms) BEGIN (0.7ms) UPDATE "people" SET "data" = 'age=>500,gender=>male', "updated_at" = '2012-12-07 15:41:50.404719' WHERE "people"."id" = 3 (1.8ms) COMMIT => true 1.9.3-p327 :014 > p => #"500", "gender"=>"male"}, created_at: "2012-12-07 15:01:53", updated_at: "2012-12-07 15:41:50"> 1.9.3-p327 :015 > exit % rails c 12-12-07 - 10:41:57 Loading development environment (Rails 3.2.9) 1.9.3-p327 :001 > p = Person.find(3) Person Load (9.3ms) SELECT "people".* FROM "people" WHERE "people"."id" = $1 LIMIT 1 [["id", 3]] => #"500", "gender"=>"male"}, created_at: "2012-12-07 15:01:53", updated_at: "2012-12-07 15:41:50"> 1.9.3-p327 :002 > 

知道这里可能会发生什么吗?

我最终将store_accessor放在一起并使用以下代码为hstore密钥添加访问器

LIB / hstore_accessor.rb

 module HstoreAccessor def self.included(base) base.extend(ClassMethods) end module ClassMethods def hstore_accessor(hstore_attribute, *keys) Array(keys).flatten.each do |key| define_method("#{key}=") do |value| send("#{hstore_attribute}=", (send(hstore_attribute) || {}).merge(key.to_s => value)) send("#{hstore_attribute}_will_change!") end define_method(key) do send(hstore_attribute) && send(hstore_attribute)[key.to_s] end end end end end ActiveRecord::Base.send(:include, HstoreAccessor) 

配置/初始化/ active_record_extensions.rb

 require "hstore_accessor" 

 class Person < ActiveRecord::Base hstore_accessor :data, :size, :shape, :smell end