My Task
model has commit callbacks that send notifications. But the task model ALSO gets touched by a bunch of associated/child records, and these really shouldn’t be sending notifications for each one.
I’ve decided to write a simple touch_without_callbacks
method that helped me acheive this.
How to touch rails columns without callbacks
create an initializer called touch_without_callbacks.rb
module TouchWithoutCallbacks
extend ActiveSupport::Concern
def touch_without_callbacks(*names, time: nil)
time ||= current_time_from_proper_timezone
attribute_names = timestamp_attributes_for_update_in_model
attribute_names |= names.map(&:to_s)
return false if attribute_names.empty?
changes = {}
attribute_names.each do |attr_name|
changes[attr_name] = time
end
primary_key = self.class.primary_key
self.class.unscoped
.where(primary_key => self[primary_key])
.update_all(changes) == 1
end
def current_time_from_proper_timezone
default_timezone == :utc ? Time.now.utc : Time.now
end
end
# include the extension into your rails models
ActiveRecord::Base.send(:include, TouchWithoutCallbacks)
So now in your rails code, you can do something like this:
task = Task.find(...)
task.touch_without_callbacks # will change the `updated_at`
# will not trigger callbacks
task.touch_without_callbacks(:reminder_at)
# will change both `updated_at` and `reminder_at`
# will not trigger callbacks
Docs on #touch
: