mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-22 22:06:50 +00:00
Merge pull request #1402 from beauby/extract-caching
Extract caching into its own module
This commit is contained in:
commit
12cd190cfc
@ -4,6 +4,7 @@ require 'active_model/serializer/array_serializer'
|
||||
require 'active_model/serializer/include_tree'
|
||||
require 'active_model/serializer/associations'
|
||||
require 'active_model/serializer/attributes'
|
||||
require 'active_model/serializer/caching'
|
||||
require 'active_model/serializer/configuration'
|
||||
require 'active_model/serializer/fieldset'
|
||||
require 'active_model/serializer/lint'
|
||||
@ -15,63 +16,19 @@ module ActiveModel
|
||||
include Configuration
|
||||
include Associations
|
||||
include Attributes
|
||||
include Caching
|
||||
require 'active_model/serializer/adapter'
|
||||
|
||||
# Matches
|
||||
# "c:/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb:1:in `<top (required)>'"
|
||||
# AND
|
||||
# "/c/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb:1:in `<top (required)>'"
|
||||
# AS
|
||||
# c/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb
|
||||
CALLER_FILE = /
|
||||
\A # start of string
|
||||
.+ # file path (one or more characters)
|
||||
(?= # stop previous match when
|
||||
:\d+ # a colon is followed by one or more digits
|
||||
:in # followed by a colon followed by in
|
||||
)
|
||||
/x
|
||||
|
||||
# Hashes contents of file for +_cache_digest+
|
||||
def self.digest_caller_file(caller_line)
|
||||
serializer_file_path = caller_line[CALLER_FILE]
|
||||
serializer_file_contents = IO.read(serializer_file_path)
|
||||
Digest::MD5.hexdigest(serializer_file_contents)
|
||||
rescue TypeError, Errno::ENOENT
|
||||
warn <<-EOF.strip_heredoc
|
||||
Cannot digest non-existent file: '#{caller_line}'.
|
||||
Please set `::_cache_digest` of the serializer
|
||||
if you'd like to cache it.
|
||||
EOF
|
||||
''.freeze
|
||||
end
|
||||
|
||||
with_options instance_writer: false, instance_reader: false do |serializer|
|
||||
serializer.class_attribute :_type, instance_reader: true
|
||||
serializer.class_attribute :_links # @api private : links definitions, @see Serializer#link
|
||||
serializer.class_attribute :_links # @api private : links definitions, @see Serializer#link
|
||||
self._links ||= {}
|
||||
serializer.class_attribute :_cache # @api private : the cache object
|
||||
serializer.class_attribute :_fragmented # @api private : @see ::fragmented
|
||||
serializer.class_attribute :_cache_key # @api private : when present, is first item in cache_key
|
||||
serializer.class_attribute :_cache_only # @api private : when fragment caching, whitelists cached_attributes. Cannot combine with except
|
||||
serializer.class_attribute :_cache_except # @api private : when fragment caching, blacklists cached_attributes. Cannot combine with only
|
||||
serializer.class_attribute :_cache_options # @api private : used by CachedSerializer, passed to _cache.fetch
|
||||
# _cache_options include:
|
||||
# expires_in
|
||||
# compress
|
||||
# force
|
||||
# race_condition_ttl
|
||||
# Passed to ::_cache as
|
||||
# serializer._cache.fetch(cache_key, @klass._cache_options)
|
||||
serializer.class_attribute :_cache_digest # @api private : Generated
|
||||
end
|
||||
|
||||
# Serializers inherit _attribute_mappings, _reflections, and _links.
|
||||
# Generates a unique digest for each serializer at load.
|
||||
def self.inherited(base)
|
||||
caller_line = caller.first
|
||||
base._links = _links.dup
|
||||
base._cache_digest = digest_caller_file(caller_line)
|
||||
super
|
||||
end
|
||||
|
||||
@ -86,43 +43,6 @@ module ActiveModel
|
||||
_links[name] = block || value
|
||||
end
|
||||
|
||||
# @api private
|
||||
# Used by FragmentCache on the CachedSerializer
|
||||
# to call attribute methods on the fragmented cached serializer.
|
||||
def self.fragmented(serializer)
|
||||
self._fragmented = serializer
|
||||
end
|
||||
|
||||
# Enables a serializer to be automatically cached
|
||||
#
|
||||
# Sets +::_cache+ object to <tt>ActionController::Base.cache_store</tt>
|
||||
# when Rails.configuration.action_controller.perform_caching
|
||||
#
|
||||
# @params options [Hash] with valid keys:
|
||||
# key : @see ::_cache_key
|
||||
# only : @see ::_cache_only
|
||||
# except : @see ::_cache_except
|
||||
# skip_digest : does not include digest in cache_key
|
||||
# all else : @see ::_cache_options
|
||||
#
|
||||
# @example
|
||||
# class PostSerializer < ActiveModel::Serializer
|
||||
# cache key: 'post', expires_in: 3.hours
|
||||
# attributes :title, :body
|
||||
#
|
||||
# has_many :comments
|
||||
# end
|
||||
#
|
||||
# @todo require less code comments. See
|
||||
# https://github.com/rails-api/active_model_serializers/pull/1249#issuecomment-146567837
|
||||
def self.cache(options = {})
|
||||
self._cache = ActiveModelSerializers.config.cache_store if ActiveModelSerializers.config.perform_caching
|
||||
self._cache_key = options.delete(:key)
|
||||
self._cache_only = options.delete(:only)
|
||||
self._cache_except = options.delete(:except)
|
||||
self._cache_options = (options.empty?) ? nil : options
|
||||
end
|
||||
|
||||
# @param resource [ActiveRecord::Base, ActiveModelSerializers::Model]
|
||||
# @return [ActiveModel::Serializer]
|
||||
# Preferentially returns
|
||||
@ -145,12 +65,6 @@ module ActiveModel
|
||||
ActiveModel::Serializer::Adapter.lookup(config.adapter)
|
||||
end
|
||||
|
||||
# Used to cache serializer name => serializer class
|
||||
# when looked up by Serializer.get_serializer_for.
|
||||
def self.serializers_cache
|
||||
@serializers_cache ||= ThreadSafe::Cache.new
|
||||
end
|
||||
|
||||
# @api private
|
||||
def self.serializer_lookup_chain_for(klass)
|
||||
chain = []
|
||||
@ -165,6 +79,12 @@ module ActiveModel
|
||||
chain
|
||||
end
|
||||
|
||||
# Used to cache serializer name => serializer class
|
||||
# when looked up by Serializer.get_serializer_for.
|
||||
def self.serializers_cache
|
||||
@serializers_cache ||= ThreadSafe::Cache.new
|
||||
end
|
||||
|
||||
# @api private
|
||||
# Find a serializer from a class and caches the lookup.
|
||||
# Preferentially retuns:
|
||||
|
||||
100
lib/active_model/serializer/caching.rb
Normal file
100
lib/active_model/serializer/caching.rb
Normal file
@ -0,0 +1,100 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
module Caching
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
with_options instance_writer: false, instance_reader: false do |serializer|
|
||||
serializer.class_attribute :_cache # @api private : the cache object
|
||||
serializer.class_attribute :_fragmented # @api private : @see ::fragmented
|
||||
serializer.class_attribute :_cache_key # @api private : when present, is first item in cache_key
|
||||
serializer.class_attribute :_cache_only # @api private : when fragment caching, whitelists cached_attributes. Cannot combine with except
|
||||
serializer.class_attribute :_cache_except # @api private : when fragment caching, blacklists cached_attributes. Cannot combine with only
|
||||
serializer.class_attribute :_cache_options # @api private : used by CachedSerializer, passed to _cache.fetch
|
||||
# _cache_options include:
|
||||
# expires_in
|
||||
# compress
|
||||
# force
|
||||
# race_condition_ttl
|
||||
# Passed to ::_cache as
|
||||
# serializer._cache.fetch(cache_key, @klass._cache_options)
|
||||
serializer.class_attribute :_cache_digest # @api private : Generated
|
||||
end
|
||||
end
|
||||
|
||||
# Matches
|
||||
# "c:/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb:1:in `<top (required)>'"
|
||||
# AND
|
||||
# "/c/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb:1:in `<top (required)>'"
|
||||
# AS
|
||||
# c/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb
|
||||
CALLER_FILE = /
|
||||
\A # start of string
|
||||
.+ # file path (one or more characters)
|
||||
(?= # stop previous match when
|
||||
:\d+ # a colon is followed by one or more digits
|
||||
:in # followed by a colon followed by in
|
||||
)
|
||||
/x
|
||||
|
||||
module ClassMethods
|
||||
def inherited(base)
|
||||
super
|
||||
caller_line = caller[1]
|
||||
base._cache_digest = digest_caller_file(caller_line)
|
||||
end
|
||||
|
||||
# Hashes contents of file for +_cache_digest+
|
||||
def digest_caller_file(caller_line)
|
||||
serializer_file_path = caller_line[CALLER_FILE]
|
||||
serializer_file_contents = IO.read(serializer_file_path)
|
||||
Digest::MD5.hexdigest(serializer_file_contents)
|
||||
rescue TypeError, Errno::ENOENT
|
||||
warn <<-EOF.strip_heredoc
|
||||
Cannot digest non-existent file: '#{caller_line}'.
|
||||
Please set `::_cache_digest` of the serializer
|
||||
if you'd like to cache it.
|
||||
EOF
|
||||
''.freeze
|
||||
end
|
||||
|
||||
# @api private
|
||||
# Used by FragmentCache on the CachedSerializer
|
||||
# to call attribute methods on the fragmented cached serializer.
|
||||
def fragmented(serializer)
|
||||
self._fragmented = serializer
|
||||
end
|
||||
|
||||
# Enables a serializer to be automatically cached
|
||||
#
|
||||
# Sets +::_cache+ object to <tt>ActionController::Base.cache_store</tt>
|
||||
# when Rails.configuration.action_controller.perform_caching
|
||||
#
|
||||
# @params options [Hash] with valid keys:
|
||||
# key : @see ::_cache_key
|
||||
# only : @see ::_cache_only
|
||||
# except : @see ::_cache_except
|
||||
# skip_digest : does not include digest in cache_key
|
||||
# all else : @see ::_cache_options
|
||||
#
|
||||
# @example
|
||||
# class PostSerializer < ActiveModel::Serializer
|
||||
# cache key: 'post', expires_in: 3.hours
|
||||
# attributes :title, :body
|
||||
#
|
||||
# has_many :comments
|
||||
# end
|
||||
#
|
||||
# @todo require less code comments. See
|
||||
# https://github.com/rails-api/active_model_serializers/pull/1249#issuecomment-146567837
|
||||
def cache(options = {})
|
||||
self._cache = ActiveModelSerializers.config.cache_store if ActiveModelSerializers.config.perform_caching
|
||||
self._cache_key = options.delete(:key)
|
||||
self._cache_only = options.delete(:only)
|
||||
self._cache_except = options.delete(:except)
|
||||
self._cache_options = (options.empty?) ? nil : options
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user