Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Override cache key and touch methods in active record when we cannot update the last modified / updated at column in database. We keep track of the changes in memcache.
module CacheKeyMonkeyPatch
module ActiveRecord
module Integration
# Returns a cache key that can be used to identify this record.
#
# ==== Examples
#
# Product.new.cache_key # => "products/new"
# Product.find(5).cache_key # => "products/5" (updated_at / last_modified_time not available)
# Person.find(5).cache_key # => "people/5-20140227181414671756000" (updated_at / last_modified_time available)
def cache_key
last_update_timestamp = Rails.cache.read(object_key)
return "#{self.class.model_name.cache_key}/#{id}-#{last_update_timestamp}" if last_update_timestamp
case
when new_record?
cached_cache_key = "#{self.class.model_name.cache_key}/new"
when timestamp = (self[:updated_at] || self.respond_to?(:last_modified_time) && self.last_modified_time)
timestamp = timestamp.to_s(:nsec)
Rails.logger.info "\e[33m READ: #{object_key} from nil to #{timestamp}"
Rails.cache.write(object_key, timestamp)
cached_cache_key = "#{self.class.model_name.cache_key}/#{id}-#{timestamp}"
else
cached_cache_key = "#{self.class.model_name.cache_key}/#{id}"
end
cached_cache_key
end
end
end
end
ActiveRecord::Base.class_eval do
include CacheKeyMonkeyPatch::ActiveRecord::Integration
end
module ActiveRecord
class Base
def update_cache_key_for_associated_belongs_to_models(event)
belongs_to_associations_to_touch = self.class.reflect_on_all_associations(:belongs_to).select { |assoc| assoc.options[:touch] }
belongs_to_associations_to_touch.each do |belongs_to_assoc|
associated_object = self.send(belongs_to_assoc.name)
associated_object.touch("PROPAGATE from #{self.class.to_s}") if associated_object
end
end
def touch(event = nil)
event ||= 'CREATE'
cached_timestamp = Rails.cache.fetch(object_key) || 'nil'
new_timestamp = Time.zone.now.to_s(:nsec)
Rails.logger.info "\e[33m #{event} #{object_key} from #{cached_timestamp} to #{new_timestamp}"
Rails.cache.write(object_key, new_timestamp)
update_cache_key_for_associated_belongs_to_models(event)
end
def object_key
"cache_key_#{self.class.model_name.i18n_key}_#{self.id}"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.