diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2017-05-18 18:12:32 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-18 18:12:32 +0200 |
commit | 75fa8dd309a84e125b59d01bf182d88419631eaa (patch) | |
tree | d76aa54a79b7bf07d6e6c5d3f6c07237e5f4af60 /activerecord/lib/active_record | |
parent | 385d9af299fbfac7f063de214d371545bafef5df (diff) | |
download | rails-75fa8dd309a84e125b59d01bf182d88419631eaa.tar.gz rails-75fa8dd309a84e125b59d01bf182d88419631eaa.tar.bz2 rails-75fa8dd309a84e125b59d01bf182d88419631eaa.zip |
Use recyclable cache keys (#29092)
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r-- | activerecord/lib/active_record/integration.rb | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/activerecord/lib/active_record/integration.rb b/activerecord/lib/active_record/integration.rb index 8e71b60b29..ed652e26aa 100644 --- a/activerecord/lib/active_record/integration.rb +++ b/activerecord/lib/active_record/integration.rb @@ -13,6 +13,15 @@ module ActiveRecord # This is +:usec+, by default. class_attribute :cache_timestamp_format, instance_writer: false self.cache_timestamp_format = :usec + + ## + # :singleton-method: + # Indicates whether to use a stable #cache_key method that is accompanied + # by a changing version in the #cache_version method. + # + # This is +false+, by default until Rails 6.0. + class_attribute :cache_versioning, instance_writer: false + self.cache_versioning = false end # Returns a +String+, which Action Pack uses for constructing a URL to this @@ -52,25 +61,47 @@ module ActiveRecord # used to generate the key: # # Person.find(5).cache_key(:updated_at, :last_reviewed_at) + # + # 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. + # + # Product.cache_versioning = true + # Product.new.cache_key # => "products/new" + # Person.find(5).cache_key # => "people/5" (even if updated_at available) def cache_key(*timestamp_names) if new_record? "#{model_name.cache_key}/new" else - timestamp = if timestamp_names.any? - max_updated_column_timestamp(timestamp_names) + if cache_version && timestamp_names.none? + "#{model_name.cache_key}/#{id}" else - max_updated_column_timestamp - end + timestamp = if timestamp_names.any? + max_updated_column_timestamp(timestamp_names) + else + max_updated_column_timestamp + end - if timestamp - timestamp = timestamp.utc.to_s(cache_timestamp_format) - "#{model_name.cache_key}/#{id}-#{timestamp}" - else - "#{model_name.cache_key}/#{id}" + if timestamp + timestamp = timestamp.utc.to_s(cache_timestamp_format) + "#{model_name.cache_key}/#{id}-#{timestamp}" + else + "#{model_name.cache_key}/#{id}" + end end end end + # Returns a cache version that can be used together with the cache key to form + # a recyclable caching scheme. By default, the #updated_at column is used for the + # cache_version, but this method can be overwritten to return something else. + # + # 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 + 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 |