module ActiveRecord::Integration
Public Class Methods
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.
# File lib/active_record/integration.rb, line 16 class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
Indicates whether to use a stable cache_key
method that is accompanied by a changing version in the cache_version
method.
This is true
, by default on Rails 5.2 and above.
# File lib/active_record/integration.rb, line 24 class_attribute :cache_versioning, instance_writer: false, default: false
Indicates whether to use a stable cache_key
method that is accompanied by a changing version in the cache_version
method on collections.
This is false
, by default until Rails 6.1.
# File lib/active_record/integration.rb, line 32 class_attribute :collection_cache_versioning, instance_writer: false, default: false
Public Instance Methods
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"
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 = false Product.find(5).cache_key # => "products/5-20071224150000" (updated_at available)
# File lib/active_record/integration.rb, line 72 def cache_key if new_record? "#{model_name.cache_key}/new" else if cache_version "#{model_name.cache_key}/#{id}" else timestamp = max_updated_column_timestamp if timestamp timestamp = timestamp.utc.to_fs(cache_timestamp_format) "#{model_name.cache_key}/#{id}-#{timestamp}" else "#{model_name.cache_key}/#{id}" end end end end
Returns a cache key along with the version.
# File lib/active_record/integration.rb, line 114 def cache_key_with_version if version = cache_version "#{cache_key}-#{version}" else cache_key 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
.
# File lib/active_record/integration.rb, line 97 def cache_version return unless cache_versioning if has_attribute?("updated_at") timestamp = updated_at_before_type_cast if can_use_fast_cache_version?(timestamp) raw_timestamp_to_cache_version(timestamp) elsif timestamp = updated_at timestamp.utc.to_fs(cache_timestamp_format) end elsif self.class.has_attribute?("updated_at") raise ActiveModel::MissingAttributeError, "missing attribute: updated_at" end end
Returns a String
, which Action Pack uses for constructing a URL to this object. The default implementation returns this record’s id as a String
, or nil
if this record’s unsaved.
For example, suppose that you have a User model, and that you have a resources :users
route. Normally, user_path
will construct a path with the user object’s ‘id’ in it:
user = User.find_by(name: 'Phusion') user_path(user) # => "/users/1"
You can override to_param
in your model to make user_path
construct a path using the user’s name instead of the user’s id:
class User < ActiveRecord::Base def to_param # overridden name end end user = User.find_by(name: 'Phusion') user_path(user) # => "/users/Phusion"
# File lib/active_record/integration.rb, line 57 def to_param # We can't use alias_method here, because method 'id' optimizes itself on the fly. id && id.to_s # Be sure to stringify the id for routes end
Private Instance Methods
Detects if the value before type cast can be used to generate a cache_version.
The fast cache version only works with a string value directly from the database.
We also must check if the timestamp format has been changed or if the timezone is not set to UTC then we cannot apply our transformations correctly.
# File lib/active_record/integration.rb, line 178 def can_use_fast_cache_version?(timestamp) timestamp.is_a?(String) && cache_timestamp_format == :usec && ActiveRecord.default_timezone == :utc && !updated_at_came_from_user? end
Converts a raw database string to ‘:usec` format.
Example:
timestamp = "2018-10-15 20:02:15.266505" raw_timestamp_to_cache_version(timestamp) # => "20181015200215266505"
PostgreSQL truncates trailing zeros, github.com/postgres/postgres/commit/3e1beda2cde3495f41290e1ece5d544525810214 to account for this we pad the output with zeros
# File lib/active_record/integration.rb, line 197 def raw_timestamp_to_cache_version(timestamp) key = timestamp.delete("- :.") if key.length < 20 key.ljust(20, "0") else key end end