From aa8749eb52d7919a438940c9218cad98d892f9ad Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 19 May 2017 14:09:09 +0200 Subject: Add cache_key_with_version and use it in ActiveSupport::Cache.expand_cache_key This retains the existing behavior of ActiveSupport::Cache.expand_cache_key (as used by etaging) where the cache key includes the version. --- activerecord/lib/active_record/integration.rb | 43 ++++++++++++++++----------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/integration.rb b/activerecord/lib/active_record/integration.rb index ed652e26aa..36ce49d518 100644 --- a/activerecord/lib/active_record/integration.rb +++ b/activerecord/lib/active_record/integration.rb @@ -7,8 +7,8 @@ module ActiveRecord included do ## # :singleton-method: - # Indicates the format used to generate the timestamp in the cache key. - # Accepts any of the symbols in Time::DATE_FORMATS. + # Indicates the format used to generate the timestamp in the cache key, if + # versioning is off. Accepts any of the symbols in Time::DATE_FORMATS. # # This is +:usec+, by default. class_attribute :cache_timestamp_format, instance_writer: false @@ -51,24 +51,16 @@ module ActiveRecord id && id.to_s # Be sure to stringify the id for routes end - # Returns a cache key that can be used to identify this record. + # Returns a stable cache key that can be used to identify this record. # # Product.new.cache_key # => "products/new" - # Product.find(5).cache_key # => "products/5" (updated_at not available) - # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available) - # - # You can also pass a list of named timestamps, and the newest in the list will be - # used to generate the key: - # - # Person.find(5).cache_key(:updated_at, :last_reviewed_at) + # Product.find(5).cache_key # => "products/5" # - # If ActiveRecord::Base.cache_versioning is turned on, no version will be included - # in the cache key. The version will instead be supplied by #cache_version. This - # separation enables recycling of cache keys. + # If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier, + # the cache key will also include a version. # - # Product.cache_versioning = true - # Product.new.cache_key # => "products/new" - # Person.find(5).cache_key # => "people/5" (even if updated_at available) + # Product.cache_versioning = false + # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available) def cache_key(*timestamp_names) if new_record? "#{model_name.cache_key}/new" @@ -77,6 +69,11 @@ module ActiveRecord "#{model_name.cache_key}/#{id}" else timestamp = if timestamp_names.any? + ActiveSupport::Deprecation.warn(<<-MSG.squish) + Specifying a timestamp name for #cache_key has been deprecated in favor of + the explicit #cache_version method that can be overwritten. + MSG + max_updated_column_timestamp(timestamp_names) else max_updated_column_timestamp @@ -99,9 +96,21 @@ module ActiveRecord # Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to # +false+ (which it is by default until Rails 6.0). def cache_version - try(:updated_at).try(:to_i) if cache_versioning + if cache_versioning && timestamp = try(:updated_at) + updated_at.utc.to_s(:usec) + end + end + + # Returns a cache key along with the version. + def cache_key_with_version + if version = cache_version + "#{cache_key}-#{version}" + else + cache_key + end end + module ClassMethods # Defines your model's +to_param+ method to generate "pretty" URLs # using +method_name+, which can be any attribute or method that -- cgit v1.2.3