我想覆盖store_accessor
的吸气剂。可以找到here。代码在这里:
# File activerecord/lib/active_record/store.rb, line 74
def store_accessor(store_attribute, *keys)
keys = keys.flatten
_store_accessors_module.module_eval do
keys.each do |key|
define_method("#{key}=") do |value|
write_store_attribute(store_attribute, key, value)
end
define_method(key) do
read_store_attribute(store_attribute, key)
end
end
end
self.stored_attributes[store_attribute] ||= []
self.stored_attributes[store_attribute] |= keys
end
我实现了我追求的功能,但是如果我还要覆盖setter,那么有一种方法对我来说不明确,这在write_store_attribute(...)
方法中(找到here)
代码在这里:
# File activerecord/lib/active_record/store.rb, line 108
def write_store_attribute(store_attribute, key, value)
attribute = initialize_store_attribute(store_attribute)
if value != attribute[key]
send :"#{store_attribute}_will_change!"
attribute[key] = value
end
end
我不理解的方法是"#{whatever_store_att}_will_change!"
。
如果我要覆盖setter,我会使用update_attributes
或update_column
。此方法是否使分配attribute[key]=value
实际修改了数据库中的字段,使其等同于update_attributes
?
答案 0 :(得分:11)
这是activemodel的更改跟踪系统的一部分,活动记录用于了解它需要写入数据库的内容(如果有的话)。
当您在记录上调用save时,activerecord会为其认为已更改的所有属性创建更新查询(如果没有更改的属性,则它根本不执行任何操作)。
activerecord为您生成的访问器会自动为您处理,但在某些情况下,告诉activerecord属性是脏的并且需要更改是有用的(例如,如果您更新某些内容,绕过通常的更改跟踪机制)
这正是这里发生的事情:当你为存储的属性设置一个键时 - rails修改了哈希(而不是分配一个新的哈希),因此需要调用_will_change!
来保持更改跟踪通知下次调用save时底层属性需要写入db。