理解" attribute_will_change!"方法

时间:2014-05-30 15:29:30

标签: ruby-on-rails ruby postgresql activerecord hstore

我想覆盖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_attributesupdate_column。此方法是否使分配attribute[key]=value实际修改了数据库中的字段,使其等同于update_attributes

1 个答案:

答案 0 :(得分:11)

这是activemodel的更改跟踪系统的一部分,活动记录用于了解它需要写入数据库的内容(如果有的话)。

当您在记录上调用save时,activerecord会为其认为已更改的所有属性创建更新查询(如果没有更改的属性,则它根本不执行任何操作)。

activerecord为您生成的访问器会自动为您处理,但在某些情况下,告诉activerecord属性是脏的并且需要更改是有用的(例如,如果您更新某些内容,绕过通常的更改跟踪机制)

这正是这里发生的事情:当你为存储的属性设置一个键时 - rails修改了哈希(而不是分配一个新的哈希),因此需要调用_will_change!来保持更改跟踪通知下次调用save时底层属性需要写入db。