Prevent unnecessary chained touches in Rails
In a lot of cases (cache invalidation mostly) touch true is a valid solution. However, current Rails touch: true chaining is over aggressive and it is possible that same record(s) will be touched multiple times or unnecessary. This quick hack will prevent that touching molestation. Takes a block within which it will limit record(s) to be touched only once.
class Disturbed
class << self
attr_accessor :records
end
def self.records
@records || Set.new
end
def self.add_record(record)
@records ||= Set.new
@records.add(record)
end
def self.clear_records
@records.clear
end
end
module DisturbedRecord
include ActiveSupport::Concern
def disturb
Disturbed.add_record(self)
end
end
module DisturbedAction
include ActiveSupport::Concern
def disturbed
begin
ActiveRecord::Base.send(:alias_method,:old_touch, :touch)
ActiveRecord::Base.send(:alias_method,:touch, :disturb)
yield
rescue Exception => e
raise e
ensure
Disturbed.records.each {|r| r.old_touch }
Disturbed.clear_records
ActiveRecord::Base.send(:alias_method, :touch, :old_touch)
ActiveRecord::Base.send(:remove_method,:old_touch)
end
end
end
ActiveRecord::Base.send(:include, DisturbedRecord)
Written by Nickolay Schwarz
Related protips
3 Responses
This looks like exactly what I need, but I'm not sure I understand if this is supposed to work automatically or I need to wrap my update code with a wrapper. Please let me know.
over 1 year ago
·
It doesn't work automatically, you need to to wrap your code in the disturbed
block like this:
disturbed do
#your code goes here
Purchase.register(current_user, params) #for example
end
Let me know if that works, I can throw you some examples in the live app as well.
over 1 year ago
·
This is great, thanks for the post. However it would be nice if we could get the core issue with current :touch implementation fixed.
Ticket for it appears to be here' https://github.com/rails/rails/issues/8759#issuecomment-49540505
It's been closed which is frustrating.
over 1 year ago
·
Have a fresh tip? Share with Coderwall community!
Post
Post a tip
Best
#Ruby
Authors
Sponsored by #native_company# — Learn More
#native_title#
#native_desc#