Module: ActiveRecord::Dirty
Track unsaved attribute changes.
A newly instantiated object is unchanged:
person = Person.find_by_name('uncle bob')
person.changed? # => false
Change the name:
person.name = 'Bob' person.changed? # => true person.name_changed? # => true person.name_was # => 'uncle bob' person.name_change # => ['uncle bob', 'Bob'] person.name = 'Bill' person.name_change # => ['uncle bob', 'Bill']
Save the changes:
person.save person.changed? # => false person.name_changed? # => false
Assigning the same value leaves the attribute unchanged:
person.name = 'Bill' person.name_changed? # => false person.name_change # => nil
Which attributes have changed?
person.name = 'bob'
person.changed # => ['name']
person.changes # => { 'name' => ['Bill', 'bob'] }
Before modifying an attribute in-place:
person.name_will_change! person.name << 'by' person.name_change # => ['uncle bob', 'uncle bobby']
Public Class Methods
included (base)
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 37 37: def self.included(base) 38: base.attribute_method_suffix '_changed?', '_change', '_will_change!', '_was' 39: base.alias_method_chain :write_attribute, :dirty 40: base.alias_method_chain :save, :dirty 41: base.alias_method_chain :save!, :dirty 42: base.alias_method_chain :update, :dirty 43: 44: base.superclass_delegating_accessor :partial_updates 45: base.partial_updates = false 46: end
Public Instance Methods
changed ()
List of attributes with unsaved changes.
person.changed # => [] person.name = 'bob' person.changed # => ['name']
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 60 60: def changed 61: changed_attributes.keys 62: end
changed? ()
Do any attributes have unsaved changes?
person.changed? # => false person.name = 'bob' person.changed? # => true
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 52 52: def changed? 53: !changed_attributes.empty? 54: end
changes ()
Map of changed attrs => [original value, new value]
person.changes # => {}
person.name = 'bob'
person.changes # => { 'name' => ['bill', 'bob'] }
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 68 68: def changes 69: changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h } 70: end
save_with_dirty (*args)
Clear changed attributes after they are saved.
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 74 74: def save_with_dirty(*args) #nodoc 75: save_without_dirty(*args) 76: ensure 77: changed_attributes.clear 78: end
save_with_dirty! (*args)
Clear changed attributes after they are saved.
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 81 81: def save_with_dirty!(*args) #nodoc 82: save_without_dirty!(*args) 83: ensure 84: changed_attributes.clear 85: end
Private Instance Methods
attribute_change (attr)
Handle *_change for method_missing.
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 99 99: def attribute_change(attr) 100: [changed_attributes[attr], __send__(attr)] if attribute_changed?(attr) 101: end
attribute_changed? (attr)
Handle *_changed? for method_missing.
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 94 94: def attribute_changed?(attr) 95: changed_attributes.include?(attr) 96: end
attribute_was (attr)
Handle *_was for method_missing.
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 104 104: def attribute_was(attr) 105: attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr) 106: end
attribute_will_change! (attr)
Handle *_will_change! for method_missing.
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 109 109: def attribute_will_change!(attr) 110: changed_attributes[attr] = clone_attribute_value(:read_attribute, attr) 111: end
changed_attributes ()
Map of change attr => original value.
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 89 89: def changed_attributes 90: @changed_attributes ||= {} 91: end
update_with_dirty ()
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 134 134: def update_with_dirty 135: if partial_updates? 136: update_without_dirty(changed) 137: else 138: update_without_dirty 139: end 140: end
write_attribute_with_dirty (attr, value)
Wrap write_attribute to remember original attribute value.
# File vendor/rails/activerecord/lib/active_record/dirty.rb, line 114 114: def write_attribute_with_dirty(attr, value) 115: attr = attr.to_s 116: 117: # The attribute already has an unsaved change. 118: unless changed_attributes.include?(attr) 119: old = clone_attribute_value(:read_attribute, attr) 120: 121: # Remember the original value if it's different. 122: typecasted = if column = column_for_attribute(attr) 123: column.type_cast(value) 124: else 125: value 126: end 127: changed_attributes[attr] = old unless old == typecasted 128: end 129: 130: # Carry on. 131: write_attribute_without_dirty(attr, value) 132: end