如何持久化依赖于rails中id值的派生属性?下面的片段似乎有用 - 有更好的轨道方式吗?
class Model < ActiveRecord::Base
....
def save
super
#derived_attr column exists in DB
self.derived_attr = compute_attr(self.id)
super
end
end
答案 0 :(得分:5)
提供了回调,因此您永远不必覆盖保存。以下代码中的before_save调用在功能上等同于问题中的所有代码。
我已将set_virtual_attr设为public,以便可以根据需要进行计算。
class Model < ActiveRecord::Base
...
# this one line is functionally equivalent to the code in the OP.
before_save :set_virtual_attr
attr_reader :virtual_attr
def set_virtual_attr
self.virtual_attr = compute_attr(self.id)
end
private
def compute_attr
...
end
end
答案 1 :(得分:3)
我认为更常被接受的方法是为虚拟属性提供自定义setter,然后在创建记录后提供after_create挂钩来设置值。
以下代码应该做你想要的。
class Virt < ActiveRecord::Base
def after_create()
self.virtual_attr = nil # Set it to anything just to invoke the setter
save # Saving will not invoke this callback again as the record exists
# Do NOT try this in after_save or you will get a Stack Overflow
end
def virtual_attr=(value)
write_attribute(:virtual_attr, "ID: #{self.id} #{value}")
end
end
在控制台中运行此功能会显示以下内容
v=Virt.new
=> #<Virt id: nil, virtual_attr: nil, created_at: nil, updated_at: nil>
>> v.save
=> true
>> v
=> #<Virt id: 8, virtual_attr: "ID: 8 ", created_at: "2009-12-23 09:25:17",
updated_at: "2009-12-23 09:25:17">
>> Virt.last
=> #<Virt id: 8, virtual_attr: "ID: 8 ", created_at: "2009-12-23 09:25:17",
updated_at: "2009-12-23 09:25:17">