diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2019-04-15 13:53:58 +0900 |
---|---|---|
committer | Ryuta Kamizono <kamipo@gmail.com> | 2019-04-15 13:53:58 +0900 |
commit | d1107f4d1e2573948d4941ac44511a0af6241f80 (patch) | |
tree | 50f8b5d9d93a0f4ae43fbf183396830c8a3878e4 /activerecord/lib | |
parent | 4ff2c934b57885e48193e2a9123599238b7a72fe (diff) | |
download | rails-d1107f4d1e2573948d4941ac44511a0af6241f80.tar.gz rails-d1107f4d1e2573948d4941ac44511a0af6241f80.tar.bz2 rails-d1107f4d1e2573948d4941ac44511a0af6241f80.zip |
Fix dirty tracking for `touch`
Before this fix, `touch` only clears dirty tracking for touched
attributes, doesn't track saved (touched) changes.
This fixes that tracks saved changes and carry over remaining changes.
Fixes #33429.
Closes #34306.
Diffstat (limited to 'activerecord/lib')
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/dirty.rb | 24 | ||||
-rw-r--r-- | activerecord/lib/active_record/locking/optimistic.rb | 3 | ||||
-rw-r--r-- | activerecord/lib/active_record/persistence.rb | 7 |
3 files changed, 29 insertions, 5 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 920a7b2038..68ac8475b0 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -166,6 +166,30 @@ module ActiveRecord result end + def _touch_row(attribute_names, time) + @_touch_attr_names = Set.new(attribute_names) + + affected_rows = super + + changes = {} + @attributes.keys.each do |attr_name| + next if @_touch_attr_names.include?(attr_name) + + if attribute_changed?(attr_name) + changes[attr_name] = _read_attribute(attr_name) + _write_attribute(attr_name, attribute_was(attr_name)) + clear_attribute_change(attr_name) + end + end + + changes_applied + changes.each { |attr_name, value| _write_attribute(attr_name, value) } + + affected_rows + ensure + @_touch_attr_names = nil + end + def _update_record(attribute_names = attribute_names_for_partial_writes) affected_rows = super changes_applied diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 4a3a31fc95..b7eecda59e 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -71,9 +71,8 @@ module ActiveRecord end def _touch_row(attribute_names, time) + @_touch_attr_names << self.class.locking_column if locking_enabled? super - ensure - clear_attribute_change(self.class.locking_column) if locking_enabled? end def _update_row(attribute_names, attempted_action = "update") diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index bc6d04b7bb..8bade8cd28 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -851,7 +851,9 @@ module ActiveRecord end attribute_names = timestamp_attributes_for_update_in_model - attribute_names |= names.map(&:to_s) + attribute_names |= names.map!(&:to_s).map! { |name| + self.class.attribute_alias?(name) ? self.class.attribute_alias(name) : name + } unless attribute_names.empty? affected_rows = _touch_row(attribute_names, time) @@ -879,8 +881,7 @@ module ActiveRecord time ||= current_time_from_proper_timezone attribute_names.each do |attr_name| - write_attribute(attr_name, time) - clear_attribute_change(attr_name) + _write_attribute(attr_name, time) end _update_row(attribute_names, "touch") |