From 877ea784e4cd0d539bdfbd15839ae3d28169b156 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Sat, 12 Jul 2014 18:30:49 -0600 Subject: Implement `_was` and `changes` for in-place mutations of AR attributes --- activemodel/lib/active_model/dirty.rb | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'activemodel') diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index d11243c4c0..ed00d8cf12 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -114,7 +114,7 @@ module ActiveModel include ActiveModel::AttributeMethods included do - attribute_method_suffix '_changed?', '_change', '_will_change!', '_was' + attribute_method_suffix '_changed?', '_change', '_will_change!', '_was', '_was=' attribute_method_affix prefix: 'reset_', suffix: '!' attribute_method_affix prefix: 'restore_', suffix: '!' end @@ -180,13 +180,26 @@ module ActiveModel attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr) end + # Handle *_was= for +method_missing+ + def attribute_was=(attr, old_value) + attributes_changed_by_setter[attr] = old_value + end + alias_method :set_attribute_was, :attribute_was= + # Restore all previous data of the provided attributes. def restore_attributes(attributes = changed) attributes.each { |attr| restore_attribute! attr } end + # Remove changes information for the provided attributes. + def clear_attribute_changes(attributes) + attributes_changed_by_setter.except!(*attributes) + end + private + alias_method :attributes_changed_by_setter, :changed_attributes # :nodoc: + # Removes current changes and makes them accessible through +previous_changes+. def changes_applied # :doc: @previously_changed = changes @@ -219,7 +232,7 @@ module ActiveModel rescue TypeError, NoMethodError end - changed_attributes[attr] = value + set_attribute_was(attr, value) end # Handle reset_*! for +method_missing+. @@ -233,7 +246,7 @@ module ActiveModel def restore_attribute!(attr) if attribute_changed?(attr) __send__("#{attr}=", changed_attributes[attr]) - changed_attributes.delete(attr) + clear_attribute_changes([attr]) end end end -- cgit v1.2.3 From 008f3da3835e47f719ba6820703ba404ff363640 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Sat, 16 Aug 2014 22:55:01 -0700 Subject: Don't expose these new APIs yet (added in 877ea78 / #16189) WARNING: don't use them! They might change or go away between future beta/RC/ patch releases! Also added a CHANGELOG entry for this. --- activemodel/lib/active_model/dirty.rb | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'activemodel') diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index ed00d8cf12..ca04f48c1c 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -114,7 +114,7 @@ module ActiveModel include ActiveModel::AttributeMethods included do - attribute_method_suffix '_changed?', '_change', '_will_change!', '_was', '_was=' + attribute_method_suffix '_changed?', '_change', '_will_change!', '_was' attribute_method_affix prefix: 'reset_', suffix: '!' attribute_method_affix prefix: 'restore_', suffix: '!' end @@ -180,26 +180,13 @@ module ActiveModel attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr) end - # Handle *_was= for +method_missing+ - def attribute_was=(attr, old_value) - attributes_changed_by_setter[attr] = old_value - end - alias_method :set_attribute_was, :attribute_was= - # Restore all previous data of the provided attributes. def restore_attributes(attributes = changed) attributes.each { |attr| restore_attribute! attr } end - # Remove changes information for the provided attributes. - def clear_attribute_changes(attributes) - attributes_changed_by_setter.except!(*attributes) - end - private - alias_method :attributes_changed_by_setter, :changed_attributes # :nodoc: - # Removes current changes and makes them accessible through +previous_changes+. def changes_applied # :doc: @previously_changed = changes @@ -249,5 +236,19 @@ module ActiveModel clear_attribute_changes([attr]) end end + + # This is necessary because `changed_attributes` might be overridden in + # other implemntations (e.g. in `ActiveRecord`) + alias_method :attributes_changed_by_setter, :changed_attributes # :nodoc: + + # Force an attribute to have a particular "before" value + def set_attribute_was(attr, old_value) + attributes_changed_by_setter[attr] = old_value + end + + # Remove changes information for the provided attributes. + def clear_attribute_changes(attributes) + attributes_changed_by_setter.except!(*attributes) + end end end -- cgit v1.2.3