aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2019-04-15 13:53:58 +0900
committerRyuta Kamizono <kamipo@gmail.com>2019-04-15 13:53:58 +0900
commitd1107f4d1e2573948d4941ac44511a0af6241f80 (patch)
tree50f8b5d9d93a0f4ae43fbf183396830c8a3878e4 /activerecord/lib/active_record
parent4ff2c934b57885e48193e2a9123599238b7a72fe (diff)
downloadrails-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/active_record')
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb24
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb3
-rw-r--r--activerecord/lib/active_record/persistence.rb7
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")