2013-11-21 58 views
1

我有下面的類:訪問屬性裏面散列列

class Profile < ActiveRecord::Base 
    serialize :data 
end 

檔案具有保持序列化哈希單列data。我想將訪問器定義爲該散列,以便我可以執行profile.name而不是profile.data['name']。這在Rails中可能嗎?

+0

這應該這樣做:'def method_missing(method,* args,&block); self [:data] [method.to_s] .presence ||超級(方法,* args,&block);結束'這是動態的,但測試'profile.respond_to?:name'會失敗 – MrYoshiji

回答

1

簡單直接的方式:

class Profile < ActiveRecord::Base 
    serialize :data 

    def name 
    self.data['name'] 
    end 

    def some_other_attribute 
    self.data['some_other_attribute'] 
    end 
end 

你可以看到如何能迅速成爲累贅,如果你有很多,你要訪問的數據散列中的屬性的。

所以這裏做一個更有活力的方式,它會工作任何這樣的頂級屬性要內data訪問:

class Profile < ActiveRecord::Base 
    serialize :data 

    def method_missing(attribute, *args, &block) 
    return super unless self.data.key? attribute 
    self.data.fetch(attribute) 
    end 

    # good practice to extend respond_to? when using method_missing 
    def respond_to?(attribute, include_private = false) 
    super || self.data.key?(attribute) 
    end 
end 

對於後一種方法,你可以只定義method_missing,然後調用任何屬於@profile,屬於data內的關鍵。因此撥打@profile.name將通過method_missing並從self.data['name']獲取值。這將適用於self.data中的任何密鑰。希望有所幫助。

延伸閱讀:

http://www.trottercashion.com/2011/02/08/rubys-define_method-method_missing-and-instance_eval.html

http://technicalpickles.com/posts/using-method_missing-and-respond_to-to-create-dynamic-methods/

1
class Profile < ActiveRecord::Base 
    serialize :data # always a hash or nil 

    def name 
    data[:name] if data 
    end 
end 
0
class Profile < ActiveRecord::Base 
    serialize :data # always a hash or nil 

    ["name", "attr2", "attr3"].each do |method| 
    define_method(method) do 
     data[method.to_sym] if data 
    end 
    end 
end 
0

Ruby是非常靈活,你的模型只是一個Ruby類。定義你想要的「訪問器」方法和你想要的輸出。

class Profile < ActiveRecord::Base 
    serialize :data 

    def name 
    data['name'] if data 
    end 
end 

但是,這種方法會導致很多重複的代碼。 Ruby的元編程功能可以幫助你解決這個問題。

如果每個配置文件包含相同的數據結構,你可以使用define_method

[:name, :age, :location, :email].each do |method| 
    define_method method do 
    data[method] if data 
    end 
end 

如果配置文件包含獨特的信息,您可以使用method_missing試圖尋找到的哈希值。

def method_missing(method, *args, &block) 
    if data && data.has_key?(method) 
    data[method] 
    else 
    super 
    end 
end 
1

我要回答我的問題。它看起來像的ActiveRecord :: Store是什麼,我想:

http://api.rubyonrails.org/classes/ActiveRecord/Store.html

所以我的課將成爲:

class Profile < ActiveRecord::Base 
    store :data, accessors: [:name], coder: JSON 
end 

我敢肯定,每個人的解決方案,工作得很好,但這是那麼幹淨。

+0

好東西,不知道那個。當我瞭解到髒模塊時,我幾乎感到興奮! http://api.rubyonrails.org/classes/ActiveModel/Dirty.html – DiegoSalazar