aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activemodel/lib/active_model/dirty.rb29
-rw-r--r--activerecord/CHANGELOG.md5
-rw-r--r--activerecord/lib/active_record/associations/has_many_association.rb2
3 files changed, 21 insertions, 15 deletions
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 <tt>*_was=</tt> 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
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 02660ae4c2..495e9c77d7 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,8 @@
+* `*_was` and `changes` now work correctly for in-place attribute changes as
+ well.
+
+ *Sean Griffin*
+
* Fix regression on after_commit that didnt fire when having nested transactions.
Fixes #16425
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb
index cf59699228..1413efaf7f 100644
--- a/activerecord/lib/active_record/associations/has_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_association.rb
@@ -103,7 +103,7 @@ module ActiveRecord
if has_cached_counter?(reflection)
counter = cached_counter_attribute_name(reflection)
owner[counter] += difference
- owner.clear_attribute_changes([counter]) # eww
+ owner.send(:clear_attribute_changes, counter) # eww
end
end