2012-12-07 36 views
2

我想在使用最新版本的activerecord-postgres-hstore gem的Rails 3.2.9项目中使用Hstore,并且我使用ActiveRecord提供的store_accessor作为值Hstore。Hstore和Rails

我的模型看起来是这样的:

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

当我进入轨道控制台这里就是我得到:

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]] 
=> #<Person id: 3, name: "Leo", data: {"age"=>"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 
=> #<Person id: 3, name: "Leo", data: {"age"=>"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]] 
=> #<Person id: 3, name: "Leo", data: {"age"=>"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 
=> #<Person id: 3, name: "Leo", data: {"age"=>"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]] 
=> #<Person id: 3, name: "Leo", data: {"age"=>"500", "gender"=>"male"}, created_at: "2012-12-07 15:01:53", updated_at: "2012-12-07 15:41:50"> 
1.9.3-p327 :002 > 

对这里可能发生什么的任何想法?

回答

12

我结束了滴速的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 
+0

超酷。不能等到R4时,这是所有原生的,但现在很好。 – MBHNYC

+0

同意,这和Postgres JSON数据类型功能是我一直在等待的功能。 –