Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding "attribute_will_change!" method

I want to overwrite the store_accessor's getter. Which can be found here. Code 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

I achieved the functionality I was after, however if I were to also overwrite the setter, there is a method that is not clear to me, which is within the write_store_attribute(...) method (found here).

The code is 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

The method I don't understand is "#{whatever_store_att}_will_change!".

If I were to overwrite the setter I would use update_attributes or update_column. Is this method making the assignment attribute[key]=value actually modify the field in the DB, making it equivalent to a update_attributes?

like image 905
lllllll Avatar asked May 30 '14 15:05

lllllll


1 Answers

This is part of activemodel's change tracking system, which active record uses to know what it needs to write to the db (if anything).

When you call save on a record, then activerecord creates an update query for all the attributes that it considers changed (and if there are no changed attributes then it does nothing at all).

The accessors that activerecord generates for you handle this for you automatically, but in some cases its useful to tell activerecord that an attribute is dirty and needs changing (for example if you update something in place, circumventing the usual change tracking mechanism).

This is exactly what happens here: when you set a key for the stored attribute - rails modifies the hash (as opposed to assigning a new hash), and so a call to _will_change! is needed to keep the change tracking informed that the underlying attribute will need writing to the db the next time save is called.

like image 126
Frederick Cheung Avatar answered Nov 12 '22 10:11

Frederick Cheung