Ruby on rails ActiveRecord派生的属性持久性,取决于id值
如何持久化依赖于rails中id值的派生属性?下面的代码片段似乎有效——有更好的rails方法吗Ruby on rails ActiveRecord派生的属性持久性,取决于id值,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,如何持久化依赖于rails中id值的派生属性?下面的代码片段似乎有效——有更好的rails方法吗 class Model < ActiveRecord::Base .... def save super #derived_attr column exists in DB self.derived_attr = compute_attr(self.id) super end end 类模型正确 >>五 => # >>最后一个 => # 我认为更普
class Model < ActiveRecord::Base
....
def save
super
#derived_attr column exists in DB
self.derived_attr = compute_attr(self.id)
super
end
end
类模型
提供了回调,因此您不必重写save。下面代码中的before_save调用在功能上等同于问题中的所有代码
我已经将set_virtual_attr公开,以便可以根据需要进行计算
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
类模型
提供了回调,因此您不必重写save。下面代码中的before_save调用在功能上等同于问题中的所有代码
我已经将set_virtual_attr公开,以便可以根据需要进行计算
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
类模型
我认为更普遍的方法是为虚拟属性提供一个自定义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
class-Virt
在控制台中运行此命令将显示以下内容
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">
v=Virt.new
=> #
>>v.保存
=>正确
>>五
=> #
>>最后一个
=> #
我认为更普遍的方法是为虚拟属性提供一个自定义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
class-Virt
在控制台中运行此命令将显示以下内容
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">
v=Virt.new
=> #
>>v.保存
=>正确
>>五
=> #
>>最后一个
=> #
我假设他在DB中有一个名为virtual_attr的列,该列基于ID。可以是,但通常属性是虚拟的,因为它们没有相应的DB列。它们通常是从现有列派生的。说到Rails,我从来没有听说过任何其他虚拟属性的定义。很好。我重新表述了使用派生属性而不是虚拟属性的问题。感谢您指出Chandra,我更新了我的答案以解决这一新的发展。我认为Steve的解决方案更好,至少对于可能不是id的派生属性的更一般情况而言,因为只要基础字段发生更改,就可以使用正确的virtual_attr值。在这种特定的情况下,如果基础字段是永不更改的id,那么就没有那么重要了。我假设他在DB中有一个名为virtual_attr的列,该列基于id。可以是,但通常属性是虚拟的,因为它们没有对应的DB列。它们通常是从现有列派生的。说到Rails,我从来没有听说过任何其他虚拟属性的定义。很好。我重新表述了使用派生属性而不是虚拟属性的问题。感谢您指出Chandra,我更新了我的答案以解决这一新的发展。我认为Steve的解决方案更好,至少对于可能不是id的派生属性的更一般情况而言,因为只要基础字段发生更改,就可以使用正确的virtual_attr值。在这种特定情况下,如果基础字段是永不更改的id,那么它就不那么重要了。