lib/active_model/dirty.rb in activemodel-3.0.pre vs lib/active_model/dirty.rb in activemodel-3.0.0.rc

- old
+ new

@@ -1,8 +1,56 @@ +require 'active_model/attribute_methods' +require 'active_support/concern' +require 'active_support/hash_with_indifferent_access' +require 'active_support/core_ext/object/duplicable' + module ActiveModel - # Track unsaved attribute changes. + # == Active Model Dirty # + # Provides a way to track changes in your object in the same way as + # Active Record does. + # + # The requirements to implement ActiveModel::Dirty are to: + # + # * <tt>include ActiveModel::Dirty</tt> in your object + # * Call <tt>define_attribute_methods</tt> passing each method you want to + # track + # * Call <tt>attr_name_will_change!</tt> before each change to the tracked + # attribute + # + # If you wish to also track previous changes on save or update, you need to + # add + # + # @previously_changed = changes + # + # inside of your save or update method. + # + # A minimal implementation could be: + # + # class Person + # + # include ActiveModel::Dirty + # + # define_attribute_methods [:name] + # + # def name + # @name + # end + # + # def name=(val) + # name_will_change! + # @name = val + # end + # + # def save + # @previously_changed = changes + # end + # + # end + # + # == Examples: + # # A newly instantiated object is unchanged: # person = Person.find_by_name('Uncle Bob') # person.changed? # => false # # Change the name: @@ -67,31 +115,27 @@ # Map of changed attrs => [original value, new value]. # person.changes # => {} # person.name = 'bob' # person.changes # => { 'name' => ['bill', 'bob'] } def changes - changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h } + changed.inject(HashWithIndifferentAccess.new){ |h, attr| h[attr] = attribute_change(attr); h } end # Map of attributes that were changed when the model was saved. # person.name # => 'bob' # person.name = 'robert' # person.save # person.previous_changes # => {'name' => ['bob, 'robert']} def previous_changes - previously_changed_attributes + @previously_changed end - private - # Map of change <tt>attr => original value</tt>. - def changed_attributes - @changed_attributes ||= {} - end + # Map of change <tt>attr => original value</tt>. + def changed_attributes + @changed_attributes ||= {} + end - # Map of fields that were changed when the model was saved - def previously_changed_attributes - @previously_changed || {} - end + private # Handle <tt>*_changed?</tt> for +method_missing+. def attribute_changed?(attr) changed_attributes.include?(attr) end