require 'active_support/concern' module ActiveRecordTweaks module Integration extend ActiveSupport::Concern # Returns a cache key that can be used to identify this record. # Timestamp is not used to allow custom caching expiration # (e.g. Cookie based caching with expiration ) # # Product.new.cache_key # => "products/new" # Product.find(5).cache_key # => "products/5" (updated_at not available) # Person.find(5).cache_key # => "people/5" (updated_at available) def cache_key_without_timestamp case when new_record? "#{self.class.model_name.cache_key}/new" else "#{self.class.model_name.cache_key}/#{id}" end end module ClassMethods # Returns a cache key for the ActiveRecord class based # based on count and maximum value of update timestamp columns # (e.g. Cookie based caching with expiration) # # Product.cache_key # => "products/0" (empty, has updated timestamp columns or not) # Product.cache_key # => "products/1" (not empty but has no updated timestamp columns) # Person.cache_key # => "people/1-20071224150000" (not empty and has updated timestamp columns) # # @param [Array<String, Symbol>] args The column name with timestamp to check def cache_key(*args) timestamp_columns = args.empty? ? [:updated_at] : args if timestamp = max_updated_column_timestamp_for_cache_key(timestamp_columns) timestamp = timestamp.utc.to_s(cache_timestamp_format) "#{self.model_name.cache_key}/all/#{self.count}-#{timestamp}" else "#{self.model_name.cache_key}/all/#{self.count}" end end def max_updated_column_timestamp_for_cache_key(timestamp_columns) available_timestamp_columns = timestamp_columns.select { |c| self.column_names.include?(c.to_s) } if (timestamps = available_timestamp_columns.map { |column| self.maximum(column) }.compact).present? timestamps.map { |ts| ts.to_time }.max end end end end end