aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/touch_later.rb
diff options
context:
space:
mode:
authorArthur Neves <arthurnn@gmail.com>2015-03-13 13:14:55 -0400
committerArthur Neves <arthurnn@gmail.com>2015-04-08 13:31:28 -0400
commit89713897830cabe49658755ddd673bbdb0a64f11 (patch)
tree2239cd3e0ccf380ea7117ad2458a75845acface2 /activerecord/lib/active_record/touch_later.rb
parent67c2deeb4be58f9f4c24f32400d41bdd355021f9 (diff)
downloadrails-89713897830cabe49658755ddd673bbdb0a64f11.tar.gz
rails-89713897830cabe49658755ddd673bbdb0a64f11.tar.bz2
rails-89713897830cabe49658755ddd673bbdb0a64f11.zip
Batch touch parent records
[fixes #18606] Make belongs_to use touch over touch_later when running the callbacks. Add more tests and small method rename Thanks Jeremy for the feedback.
Diffstat (limited to 'activerecord/lib/active_record/touch_later.rb')
-rw-r--r--activerecord/lib/active_record/touch_later.rb50
1 files changed, 50 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/touch_later.rb b/activerecord/lib/active_record/touch_later.rb
new file mode 100644
index 0000000000..4352a0ffea
--- /dev/null
+++ b/activerecord/lib/active_record/touch_later.rb
@@ -0,0 +1,50 @@
+module ActiveRecord
+ # = Active Record Touch Later
+ module TouchLater
+ extend ActiveSupport::Concern
+
+ included do
+ before_commit_without_transaction_enrollment :touch_deferred_attributes
+ end
+
+ def touch_later(*names) # :nodoc:
+ raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
+
+ @_defer_touch_attrs ||= timestamp_attributes_for_update_in_model
+ @_defer_touch_attrs |= names
+ @_touch_time = current_time_from_proper_timezone
+
+ surreptitiously_touch @_defer_touch_attrs
+ self.class.connection.add_transaction_record self
+ end
+
+ def touch(*names, time: nil) # :nodoc:
+ if has_defer_touch_attrs?
+ names |= @_defer_touch_attrs
+ end
+ super(*names, time: time)
+ end
+
+ private
+ def surreptitiously_touch(attrs)
+ attrs.each { |attr| write_attribute attr, @_touch_time }
+ clear_attribute_changes attrs
+ end
+
+ 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
+ end
+ end
+
+ def has_defer_touch_attrs?
+ defined?(@_defer_touch_attrs) && @_defer_touch_attrs.present?
+ end
+
+ def touching_delayed_records?
+ defined?(@_touching_delayed_records) && @_touching_delayed_records
+ end
+ end
+end