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