Active Model Dirty¶↑
Provides a way to track changes in your object in the same way as Active Record does.
The requirements for implementingActiveModel::Dirty are:
include ActiveModel::Dirtyin your object.Call
define_attribute_methodspassing each method you want to track.Call
*_will_change!before each change to the tracked attribute.Call
changes_appliedafter the changes are persisted.Call
clear_changes_informationwhen you want to reset the changes information.Call
restore_attributeswhen you want to restore previous data.
A minimal implementation could be:
classPersonincludeActiveModel::Dirtydefine_attribute_methods:namedefinitialize@name =nilenddefname@nameenddefname=(val)name_will_change!unlessval==@name@name =valenddefsave# do persistence workchanges_appliedenddefreload!# get the values from the persistence layerclear_changes_informationenddefrollback!restore_attributesendend
A newly instantiatedPerson object is unchanged:
person =Person.newperson.changed?# => false
Change the name:
person.name ='Bob'person.changed?# => trueperson.name_changed?# => trueperson.name_changed?(from:nil,to:"Bob")# => trueperson.name_was# => nilperson.name_change# => [nil, "Bob"]person.name ='Bill'person.name_change# => [nil, "Bill"]
Save the changes:
person.saveperson.changed?# => falseperson.name_changed?# => false
Reset the changes:
person.previous_changes# => {"name" => [nil, "Bill"]}person.name_previously_changed?# => trueperson.name_previously_changed?(from:nil,to:"Bill")# => trueperson.name_previous_change# => [nil, "Bill"]person.name_previously_was# => nilperson.reload!person.previous_changes# => {}
Rollback the changes:
person.name ="Uncle Bob"person.rollback!person.name# => "Bill"person.name_changed?# => false
Assigning the same value leaves the attribute unchanged:
person.name ='Bill'person.name_changed?# => falseperson.name_change# => nil
Which attributes have changed?
person.name ='Bob'person.changed# => ["name"]person.changes# => {"name" => ["Bill", "Bob"]}
If an attribute is modified in-place then make use of*_will_change! to mark that the attribute is changing. Otherwise Active Model can’t track changes to in-place attributes. Note that Active Record can detect in-place modifications automatically. You do not need to call*_will_change! on Active Record models.
person.name_will_change!person.name_change# => ["Bill", "Bill"]person.name<<'y'person.name_change# => ["Bill", "Billy"]
Methods can be invoked asname_changed? or by passing an argument to the generic methodattribute_changed?("name").
- #
- A
- C
- P
- R
Instance Public methods
*_changeLink
This method is generated for each attribute.
Returns the old and the new value of the attribute.
person =Person.newperson.name ='Nick'person.name_change# => [nil, 'Nick']
Source:on GitHub
# File activemodel/lib/active_model/dirty.rb, line 155*_changed?Link
This method is generated for each attribute.
Returns true if the attribute has unsaved changes.
person =Person.newperson.name ='Andrew'person.name_changed?# => true
Source:on GitHub
# File activemodel/lib/active_model/dirty.rb, line 144*_previous_changeLink
This method is generated for each attribute.
Returns the old and the new value of the attribute before the last save.
person =Person.newperson.name ='Emmanuel'person.saveperson.name_previous_change# => [nil, 'Emmanuel']
Source:on GitHub
# File activemodel/lib/active_model/dirty.rb, line 193*_previously_changed?(**options)Link
This method is generated for each attribute.
Returns true if the attribute previously had unsaved changes.
person =Person.newperson.name ='Britanny'person.saveperson.name_previously_changed?# => trueperson.name_previously_changed?(from:nil,to:'Britanny')# => true
Source:on GitHub
# File activemodel/lib/active_model/dirty.rb, line 129*_previously_wasLink
This method is generated for each attribute.
Returns the old value of the attribute before the last save.
person =Person.newperson.name ='Sage'person.saveperson.name_previously_was# => nil
Source:on GitHub
# File activemodel/lib/active_model/dirty.rb, line 205*_wasLink
This method is generated for each attribute.
Returns the old value of the attribute.
person =Person.new(name:'Steph')person.name ='Stephanie'person.name_was# => 'Steph'
Source:on GitHub
# File activemodel/lib/active_model/dirty.rb, line 182*_will_change!Link
This method is generated for each attribute.
If an attribute is modified in-place then make use of*_will_change! to mark that the attribute is changing. Otherwise ActiveModel can’t track changes to in-place attributes. Note that Active Record can detect in-place modifications automatically. You do not need to call*_will_change! on Active Record models.
person =Person.new('Sandy')person.name_will_change!person.name_change# => ['Sandy', 'Sandy']
Source:on GitHub
# File activemodel/lib/active_model/dirty.rb, line 166attribute_changed?(attr_name, **options)Link
Dispatch target for*_changed? attribute methods.
attribute_previously_changed?(attr_name, **options)Link
Dispatch target for*_previously_changed? attribute methods.
attribute_previously_was(attr_name)Link
Dispatch target for*_previously_was attribute methods.
changed()Link
Returns an array with the name of the attributes with unsaved changes.
person.changed# => []person.name ='bob'person.changed# => ["name"]
changed?()Link
Returnstrue if any of the attributes has unsaved changes,false otherwise.
person.changed?# => falseperson.name ='bob'person.changed?# => true
changed_attributes()Link
Returns a hash of the attributes with unsaved changes indicating their original values likeattr => original value.
person.name# => "bob"person.name ='robert'person.changed_attributes# => {"name" => "bob"}
changes()Link
Returns a hash of changed attributes indicating their original and new values likeattr => [original value, new value].
person.changes# => {}person.name ='bob'person.changes# => { "name" => ["bill", "bob"] }
changes_applied()Link
Clears dirty data and moveschanges toprevious_changes andmutations_from_database tomutations_before_last_save respectively.
clear_*_changeLink
This method is generated for each attribute.
Clears all dirty data of the attribute: current changes and previous changes.
person =Person.new(name:'Chris')person.name ='Jason'person.name_change# => ['Chris', 'Jason']person.clear_name_changeperson.name_change# => nil
clear_attribute_changes(attr_names)Link
clear_changes_information()Link
Clears all dirty data: current changes and previous changes.
previous_changes()Link
Returns a hash of attributes that were changed before the model was saved.
person.name# => "bob"person.name ='robert'person.saveperson.previous_changes# => {"name" => ["bob", "robert"]}