aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/touch_later.rb
diff options
context:
space:
mode:
authorArthur Neves <arthurnn@gmail.com>2015-12-06 16:35:05 -0500
committerArthur Neves <arthurnn@gmail.com>2015-12-06 16:53:00 -0500
commite7c48db509f1b712c2a72a3ff7f27e3e8b7b4868 (patch)
tree3c4038204f37e5cb296b4f980ef9e5b5b318a23c /activerecord/lib/active_record/touch_later.rb
parentff891616ac8a5c41f1fa2aba6c747d81f0782198 (diff)
downloadrails-e7c48db509f1b712c2a72a3ff7f27e3e8b7b4868.tar.gz
rails-e7c48db509f1b712c2a72a3ff7f27e3e8b7b4868.tar.bz2
rails-e7c48db509f1b712c2a72a3ff7f27e3e8b7b4868.zip
Make sure we touch all the parents when touch_later.
The problem was that when saving an object, we would call touch_later on the parent which wont be saved immediteally, and it wont call any callbacks. That was working one level up because we were calling touch, during the touch_later commit phase. However that still didnt solve the problem when you have a 3+ levels of parents to be touched, as calling touch would affect the parent, but it would be too late to run callbacks on its grand-parent. The solution for this, is instead, call touch_later upwards when the first touch_later is called. So we make sure all the timestamps are updated without relying on callbacks. This also removed the hard dependency BelongsTo builder had with the TouchLater module. So we can still have the old behaviour if TouchLater module is not included. [fixes 5f5e6d924973003c105feb711cefdb726f312768] [related #19324]
Diffstat (limited to 'activerecord/lib/active_record/touch_later.rb')
-rw-r--r--activerecord/lib/active_record/touch_later.rb16
1 files changed, 12 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/touch_later.rb b/activerecord/lib/active_record/touch_later.rb
index 4352a0ffea..9a80a63e28 100644
--- a/activerecord/lib/active_record/touch_later.rb
+++ b/activerecord/lib/active_record/touch_later.rb
@@ -16,6 +16,13 @@ module ActiveRecord
surreptitiously_touch @_defer_touch_attrs
self.class.connection.add_transaction_record self
+
+ # touch the parents as we are not calling the after_save callbacks
+ self.class.reflect_on_all_associations(:belongs_to).each do |r|
+ if touch = r.options[:touch]
+ ActiveRecord::Associations::Builder::BelongsTo.touch_record(self, r.foreign_key, r.name, touch, :touch_later)
+ end
+ end
end
def touch(*names, time: nil) # :nodoc:
@@ -26,6 +33,7 @@ module ActiveRecord
end
private
+
def surreptitiously_touch(attrs)
attrs.each { |attr| write_attribute attr, @_touch_time }
clear_attribute_changes attrs
@@ -33,9 +41,8 @@ module ActiveRecord
def touch_deferred_attributes
if has_defer_touch_attrs? && persisted?
- @_touching_delayed_records = true
touch(*@_defer_touch_attrs, time: @_touch_time)
- @_touching_delayed_records, @_defer_touch_attrs, @_touch_time = nil, nil, nil
+ @_defer_touch_attrs, @_touch_time = nil, nil
end
end
@@ -43,8 +50,9 @@ module ActiveRecord
defined?(@_defer_touch_attrs) && @_defer_touch_attrs.present?
end
- def touching_delayed_records?
- defined?(@_touching_delayed_records) && @_touching_delayed_records
+ def belongs_to_touch_method
+ :touch_later
end
+
end
end