2012-12-07 54 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數據類型功能是我一直在等待的功能。 –