我有下面的類:訪問屬性裏面散列列
class Profile < ActiveRecord::Base
serialize :data
end
檔案具有保持序列化哈希單列data
。我想將訪問器定義爲該散列,以便我可以執行profile.name
而不是profile.data['name']
。這在Rails中可能嗎?
我有下面的類:訪問屬性裏面散列列
class Profile < ActiveRecord::Base
serialize :data
end
檔案具有保持序列化哈希單列data
。我想將訪問器定義爲該散列,以便我可以執行profile.name
而不是profile.data['name']
。這在Rails中可能嗎?
簡單直接的方式:
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/
class Profile < ActiveRecord::Base
serialize :data # always a hash or nil
def name
data[:name] if data
end
end
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
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
我要回答我的問題。它看起來像的ActiveRecord :: Store是什麼,我想:
http://api.rubyonrails.org/classes/ActiveRecord/Store.html
所以我的課將成爲:
class Profile < ActiveRecord::Base
store :data, accessors: [:name], coder: JSON
end
我敢肯定,每個人的解決方案,工作得很好,但這是那麼幹淨。
好東西,不知道那個。當我瞭解到髒模塊時,我幾乎感到興奮! http://api.rubyonrails.org/classes/ActiveModel/Dirty.html – DiegoSalazar
這應該這樣做:'def method_missing(method,* args,&block); self [:data] [method.to_s] .presence ||超級(方法,* args,&block);結束'這是動態的,但測試'profile.respond_to?:name'會失敗 – MrYoshiji