理解"attribute_will_change!" 方法

lll*_*lll 5 ruby postgresql activerecord ruby-on-rails hstore

我想覆盖这个store_accessor吸气剂.哪个可以在这里找到.代码在这里:

# 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
Run Code Online (Sandbox Code Playgroud)

我实现了我所追求的功能,但是如果我还要覆盖setter,那么有一种方法对我来说并不清楚,这是在write_store_attribute(...)方法中(在这里找到).

代码在这里:

# 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
Run Code Online (Sandbox Code Playgroud)

我不明白的方法是"#{whatever_store_att}_will_change!".

如果我要覆盖我会使用的设置器update_attributesupdate_column.这种方法是否使分配attribute[key]=value实际修改了DB中的字段,使其等同于update_attributes

Fre*_*ung 12

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

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

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

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