diff --git a/lib/active_model/serializer/caching.rb b/lib/active_model/serializer/caching.rb index 077cb569..1f893189 100644 --- a/lib/active_model/serializer/caching.rb +++ b/lib/active_model/serializer/caching.rb @@ -1,5 +1,6 @@ module ActiveModel class Serializer + UndefinedCacheKey = Class.new(StandardError) module Caching extend ActiveSupport::Concern @@ -145,6 +146,172 @@ module ActiveModel perform_caching? && cache_store && (_cache_only && !_cache_except || !_cache_only && _cache_except) end + + # Read cache from cache_store + # @return [Hash] + def cache_read_multi(collection_serializer, adapter_instance, include_tree) + return {} if ActiveModelSerializers.config.cache_store.blank? + + keys = object_cache_keys(collection_serializer, adapter_instance, include_tree) + + return {} if keys.blank? + + ActiveModelSerializers.config.cache_store.read_multi(*keys) + end + + # Find all cache_key for the collection_serializer + # @param serializers [ActiveModel::Serializer::CollectionSerializer] + # @param adapter_instance [ActiveModelSerializers::Adapter::Base] + # @param include_tree [ActiveModel::Serializer::IncludeTree] + # @return [Array] all cache_key of collection_serializer + def object_cache_keys(collection_serializer, adapter_instance, include_tree) + cache_keys = [] + + collection_serializer.each do |serializer| + cache_keys << object_cache_key(serializer, adapter_instance) + + serializer.associations(include_tree).each do |association| + if association.serializer.respond_to?(:each) + association.serializer.each do |sub_serializer| + cache_keys << object_cache_key(sub_serializer, adapter_instance) + end + else + cache_keys << object_cache_key(association.serializer, adapter_instance) + end + end + end + + cache_keys.compact.uniq + end + + # @return [String, nil] the cache_key of the serializer or nil + def object_cache_key(serializer, adapter_instance) + return unless serializer.present? && serializer.object.present? + + serializer.class.cache_enabled? ? serializer.cache_key(adapter_instance) : nil + end + end + + # Get attributes from @cached_attributes + # @return [Hash] cached attributes + # def cached_attributes(fields, adapter_instance) + def cached_fields(fields, adapter_instance) + cache_check(adapter_instance) do + attributes(fields) + end + end + + def cache_check(adapter_instance) + if self.class.cache_enabled? + self.class.cache_store.fetch(cache_key(adapter_instance), self.class._cache_options) do + yield + end + elsif self.class.fragment_cache_enabled? + fetch_fragment_cache(adapter_instance) + else + yield + end + end + + # 1. Create a CachedSerializer and NonCachedSerializer from the serializer class + # 2. Serialize the above two with the given adapter + # 3. Pass their serializations to the adapter +::fragment_cache+ + def fetch_fragment_cache(adapter_instance) + # It will split the serializer into two, one that will be cached and one that will not + + # Given a resource name + # 1. Dynamically creates a CachedSerializer and NonCachedSerializer + # for a given class 'name' + # 2. Call + # CachedSerializer.cache(serializer._cache_options) + # CachedSerializer.fragmented(serializer) + # NonCachedSerializer.cache(serializer._cache_options) + # 3. Build a hash keyed to the +cached+ and +non_cached+ serializers + # 4. Call +cached_attributes+ on the serializer class and the above hash + # 5. Return the hash + # + # @example + # When +name+ is User::Admin + # creates the Serializer classes (if they don't exist). + # CachedUser_AdminSerializer + # NonCachedUser_AdminSerializer + # + serializer_class_name = self.class.name.gsub('::'.freeze, '_'.freeze) + cached_serializer = _get_or_create_fragment_serializer "Cached#{serializer_class_name}" + non_cached_serializer = _get_or_create_fragment_serializer "NonCached#{serializer_class_name}" + + self.class._cache_options ||= {} + self.class._cache_options[:key] = self.class._cache_key if self.class._cache_key + cached_serializer.cache(self.class._cache_options) + + cached_serializer.type(self.class._type) + non_cached_serializer.type(self.class._type) + + non_cached_serializer.fragmented(self) + cached_serializer.fragmented(self) + + # Given a hash of its cached and non-cached serializers + # 1. Determine cached attributes from serializer class options + # 2. Add cached attributes to cached Serializer + # 3. Add non-cached attributes to non-cached Serializer + attributes = self.class._attributes + cache_only = self.class._cache_only + cached_attributes = cache_only ? cache_only : attributes - self.class._cache_except + non_cached_attributes = attributes - cached_attributes + attributes_keys = self.class._attributes_keys + + cached_attributes.each do |attribute| + options = attributes_keys[attribute] || {} + cached_serializer.attribute(attribute, options) + end + non_cached_attributes.each do |attribute| + options = attributes_keys[attribute] || {} + non_cached_serializer.attribute(attribute, options) + end + + # Get serializable hash from both + cached_hash = ActiveModelSerializers::SerializableResource.new( + object, + serializer: cached_serializer, + adapter: adapter_instance.class + ).serializable_hash + non_cached_hash = ActiveModelSerializers::SerializableResource.new( + object, + serializer: non_cached_serializer, + adapter: adapter_instance.class + ).serializable_hash + + # Merge both results + adapter_instance.fragment_cache(cached_hash, non_cached_hash) + end + + def _get_or_create_fragment_serializer(name) + return Object.const_get(name) if Object.const_defined?(name) + Object.const_set(name, Class.new(ActiveModel::Serializer)) + end + + def cache_key(adapter_instance) + return @cache_key if defined?(@cache_key) + + parts = [] + parts << object_cache_key + parts << adapter_instance.cached_name + parts << self.class._cache_digest unless self.class._skip_digest? + @cache_key = parts.join('/') + end + + # Use object's cache_key if available, else derive a key from the object + # Pass the `key` option to the `cache` declaration or override this method to customize the cache key + def object_cache_key + if object.respond_to?(:cache_key) + object.cache_key + elsif (serializer_cache_key = (self.class._cache_key || self.class._cache_options[:key])) + object_time_safe = object.updated_at + object_time_safe = object_time_safe.strftime('%Y%m%d%H%M%S%9N') if object_time_safe.respond_to?(:strftime) + "#{serializer_cache_key}/#{object.id}-#{object_time_safe}" + else + fail UndefinedCacheKey, "#{object.class} must define #cache_key, or the 'key:' option must be passed into '#{self.class}.cache'" + end end end end diff --git a/lib/active_model_serializers.rb b/lib/active_model_serializers.rb index 15551f4b..6241fac1 100644 --- a/lib/active_model_serializers.rb +++ b/lib/active_model_serializers.rb @@ -6,8 +6,6 @@ require 'active_support/json' module ActiveModelSerializers extend ActiveSupport::Autoload autoload :Model - autoload :CachedSerializer - autoload :FragmentCache autoload :Callbacks autoload :Deserialization autoload :SerializableResource diff --git a/lib/active_model_serializers/adapter/attributes.rb b/lib/active_model_serializers/adapter/attributes.rb index 95189233..50e958f1 100644 --- a/lib/active_model_serializers/adapter/attributes.rb +++ b/lib/active_model_serializers/adapter/attributes.rb @@ -25,33 +25,6 @@ module ActiveModelSerializers serializer.map { |s| Attributes.new(s, instance_options).serializable_hash(options) } end - # Read cache from cache_store - # @return [Hash] - def cache_read_multi - return {} if ActiveModelSerializers.config.cache_store.blank? - - keys = CachedSerializer.object_cache_keys(serializer, self, @include_tree) - - return {} if keys.blank? - - ActiveModelSerializers.config.cache_store.read_multi(*keys) - end - - # Set @cached_attributes - def cache_attributes - return if @cached_attributes.present? - - @cached_attributes = cache_read_multi - end - - # Get attributes from @cached_attributes - # @return [Hash] cached attributes - def cached_attributes(cached_serializer) - return yield unless cached_serializer.cached? - - @cached_attributes.fetch(cached_serializer.cache_key(self)) { yield } - end - def serializable_hash_for_single_resource(options) resource = resource_object_for(options) relationships = resource_relationships(options) @@ -80,13 +53,20 @@ module ActiveModelSerializers json end - def resource_object_for(options) - cached_serializer = CachedSerializer.new(serializer) + # Set @cached_attributes + def cache_attributes + return if @cached_attributes.present? - cached_attributes(cached_serializer) do - cached_serializer.cache_check(self) do - serializer.attributes(options[:fields]) + @cached_attributes = ActiveModel::Serializer.cache_read_multi(serializer, self, @include_tree) + end + + def resource_object_for(options) + if serializer.class.cache_enabled? + @cached_attributes.fetch(serializer.cache_key(self)) do + serializer.cached_fields(options[:fields], self) end + else + serializer.cached_fields(options[:fields], self) end end end diff --git a/lib/active_model_serializers/adapter/base.rb b/lib/active_model_serializers/adapter/base.rb index 9b15c6ff..1a366139 100644 --- a/lib/active_model_serializers/adapter/base.rb +++ b/lib/active_model_serializers/adapter/base.rb @@ -36,7 +36,7 @@ module ActiveModelSerializers end def cache_check(serializer) - CachedSerializer.new(serializer).cache_check(self) do + serializer.cache_check(self) do yield end end diff --git a/lib/active_model_serializers/cached_serializer.rb b/lib/active_model_serializers/cached_serializer.rb deleted file mode 100644 index 09b906ed..00000000 --- a/lib/active_model_serializers/cached_serializer.rb +++ /dev/null @@ -1,87 +0,0 @@ -module ActiveModelSerializers - class CachedSerializer - UndefinedCacheKey = Class.new(StandardError) - - def initialize(serializer) - @cached_serializer = serializer - @klass = @cached_serializer.class - end - - def cache_check(adapter_instance) - if cached? - @klass._cache.fetch(cache_key(adapter_instance), @klass._cache_options) do - yield - end - elsif fragment_cached? - FragmentCache.new(adapter_instance, @cached_serializer, adapter_instance.instance_options).fetch - else - yield - end - end - - def cached? - @klass.cache_enabled? - end - - def fragment_cached? - @klass.fragment_cache_enabled? - end - - def cache_key(adapter_instance) - return @cache_key if defined?(@cache_key) - - parts = [] - parts << object_cache_key - parts << adapter_instance.cached_name - parts << @klass._cache_digest unless @klass._skip_digest? - @cache_key = parts.join('/') - end - - # Use object's cache_key if available, else derive a key from the object - # Pass the `key` option to the `cache` declaration or override this method to customize the cache key - def object_cache_key - if @cached_serializer.object.respond_to?(:cache_key) - @cached_serializer.object.cache_key - elsif (cache_key = (@klass._cache_key || @klass._cache_options[:key])) - object_time_safe = @cached_serializer.object.updated_at - object_time_safe = object_time_safe.strftime('%Y%m%d%H%M%S%9N') if object_time_safe.respond_to?(:strftime) - "#{cache_key}/#{@cached_serializer.object.id}-#{object_time_safe}" - else - fail UndefinedCacheKey, "#{@cached_serializer.object.class} must define #cache_key, or the 'key:' option must be passed into '#{@klass}.cache'" - end - end - - # find all cache_key for the collection_serializer - # @param serializers [ActiveModel::Serializer::CollectionSerializer] - # @param adapter_instance [ActiveModelSerializers::Adapter::Base] - # @param include_tree [ActiveModel::Serializer::IncludeTree] - # @return [Array] all cache_key of collection_serializer - def self.object_cache_keys(serializers, adapter_instance, include_tree) - cache_keys = [] - - serializers.each do |serializer| - cache_keys << object_cache_key(serializer, adapter_instance) - - serializer.associations(include_tree).each do |association| - if association.serializer.respond_to?(:each) - association.serializer.each do |sub_serializer| - cache_keys << object_cache_key(sub_serializer, adapter_instance) - end - else - cache_keys << object_cache_key(association.serializer, adapter_instance) - end - end - end - - cache_keys.compact.uniq - end - - # @return [String, nil] the cache_key of the serializer or nil - def self.object_cache_key(serializer, adapter_instance) - return unless serializer.present? && serializer.object.present? - - cached_serializer = new(serializer) - cached_serializer.cached? ? cached_serializer.cache_key(adapter_instance) : nil - end - end -end diff --git a/lib/active_model_serializers/fragment_cache.rb b/lib/active_model_serializers/fragment_cache.rb deleted file mode 100644 index 78f0f278..00000000 --- a/lib/active_model_serializers/fragment_cache.rb +++ /dev/null @@ -1,118 +0,0 @@ -module ActiveModelSerializers - class FragmentCache - attr_reader :serializer - - def initialize(adapter, serializer, options) - @instance_options = options - @adapter = adapter - @serializer = serializer - end - - # 1. Create a CachedSerializer and NonCachedSerializer from the serializer class - # 2. Serialize the above two with the given adapter - # 3. Pass their serializations to the adapter +::fragment_cache+ - def fetch - object = serializer.object - - # It will split the serializer into two, one that will be cached and one that will not - serializers = fragment_serializer - - # Get serializable hash from both - cached_hash = serialize(object, serializers[:cached]) - non_cached_hash = serialize(object, serializers[:non_cached]) - - # Merge both results - adapter.fragment_cache(cached_hash, non_cached_hash) - end - - protected - - attr_reader :instance_options, :adapter - - private - - def serialize(object, serializer_class) - SerializableResource.new( - object, - serializer: serializer_class, - adapter: adapter.class - ).serializable_hash - end - - # Given a hash of its cached and non-cached serializers - # 1. Determine cached attributes from serializer class options - # 2. Add cached attributes to cached Serializer - # 3. Add non-cached attributes to non-cached Serializer - def cache_attributes(serializers) - klass = serializer.class - attributes = klass._attributes - cache_only = klass._cache_only - cached_attributes = cache_only ? cache_only : attributes - klass._cache_except - non_cached_attributes = attributes - cached_attributes - attributes_keys = klass._attributes_keys - - add_attributes_to_serializer(serializers[:cached], cached_attributes, attributes_keys) - add_attributes_to_serializer(serializers[:non_cached], non_cached_attributes, attributes_keys) - end - - def add_attributes_to_serializer(serializer, attributes, attributes_keys) - attributes.each do |attribute| - options = attributes_keys[attribute] || {} - serializer.attribute(attribute, options) - end - end - - # Given a resource name - # 1. Dynamically creates a CachedSerializer and NonCachedSerializer - # for a given class 'name' - # 2. Call - # CachedSerializer.cache(serializer._cache_options) - # CachedSerializer.fragmented(serializer) - # NonCachedSerializer.cache(serializer._cache_options) - # 3. Build a hash keyed to the +cached+ and +non_cached+ serializers - # 4. Call +cached_attributes+ on the serializer class and the above hash - # 5. Return the hash - # - # @example - # When +name+ is User::Admin - # creates the Serializer classes (if they don't exist). - # CachedUser_AdminSerializer - # NonCachedUser_AdminSerializer - # - def fragment_serializer - klass = serializer.class - serializer_class_name = to_valid_const_name(klass.name) - - cached = "Cached#{serializer_class_name}" - non_cached = "NonCached#{serializer_class_name}" - - cached_serializer = get_or_create_serializer(cached) - non_cached_serializer = get_or_create_serializer(non_cached) - - klass._cache_options ||= {} - cache_key = klass._cache_key - klass._cache_options[:key] = cache_key if cache_key - cached_serializer.cache(klass._cache_options) - - type = klass._type - cached_serializer.type(type) - non_cached_serializer.type(type) - - non_cached_serializer.fragmented(serializer) - cached_serializer.fragmented(serializer) - - serializers = { cached: cached_serializer, non_cached: non_cached_serializer } - cache_attributes(serializers) - serializers - end - - def get_or_create_serializer(name) - return Object.const_get(name) if Object.const_defined?(name) - Object.const_set(name, Class.new(ActiveModel::Serializer)) - end - - def to_valid_const_name(name) - name.gsub('::', '_') - end - end -end diff --git a/test/active_model_serializers/cached_serializer_test.rb b/test/active_model_serializers/cached_serializer_test.rb deleted file mode 100644 index e9b3ff45..00000000 --- a/test/active_model_serializers/cached_serializer_test.rb +++ /dev/null @@ -1,80 +0,0 @@ -require 'test_helper' -module ActiveModelSerializers - module Adapter - class CachedSerializerTest < ActiveSupport::TestCase - def test_cached_false_without_cache_store - cached_serializer = build do |serializer| - serializer._cache = nil - end - refute cached_serializer.cached? - end - - def test_cached_true_with_cache_store_and_without_cache_only_and_cache_except - cached_serializer = build do |serializer| - serializer._cache = Object - end - assert cached_serializer.cached? - end - - def test_cached_false_with_cache_store_and_with_cache_only - cached_serializer = build do |serializer| - serializer._cache = Object - serializer._cache_only = [:name] - end - refute cached_serializer.cached? - end - - def test_cached_false_with_cache_store_and_with_cache_except - cached_serializer = build do |serializer| - serializer._cache = Object - serializer._cache_except = [:content] - end - refute cached_serializer.cached? - end - - def test_fragment_cached_false_without_cache_store - cached_serializer = build do |serializer| - serializer._cache = nil - serializer._cache_only = [:name] - end - refute cached_serializer.fragment_cached? - end - - def test_fragment_cached_true_with_cache_store_and_cache_only - cached_serializer = build do |serializer| - serializer._cache = Object - serializer._cache_only = [:name] - end - assert cached_serializer.fragment_cached? - end - - def test_fragment_cached_true_with_cache_store_and_cache_except - cached_serializer = build do |serializer| - serializer._cache = Object - serializer._cache_except = [:content] - end - assert cached_serializer.fragment_cached? - end - - def test_fragment_cached_false_with_cache_store_and_cache_except_and_cache_only - cached_serializer = build do |serializer| - serializer._cache = Object - serializer._cache_except = [:content] - serializer._cache_only = [:name] - end - refute cached_serializer.fragment_cached? - end - - private - - def build - serializer = Class.new(ActiveModel::Serializer) - serializer._cache_key = nil - serializer._cache_options = nil - yield serializer if block_given? - serializer_instance = serializer.new(Object) - CachedSerializer.new(serializer_instance) - end - end - end -end diff --git a/test/active_model_serializers/fragment_cache_test.rb b/test/active_model_serializers/fragment_cache_test.rb deleted file mode 100644 index b44b9052..00000000 --- a/test/active_model_serializers/fragment_cache_test.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'test_helper' -module ActiveModelSerializers - class FragmentCacheTest < ActiveSupport::TestCase - def setup - super - @spam = Spam::UnrelatedLink.new(id: 'spam-id-1') - @author = Author.new(name: 'Joao M. D. Moura') - @role = Role.new(name: 'Great Author', description: nil) - @role.author = [@author] - @role_serializer = RoleSerializer.new(@role) - @spam_serializer = Spam::UnrelatedLinkSerializer.new(@spam) - adapter = ActiveModelSerializers::Adapter.configured_adapter - @role_hash = FragmentCache.new(adapter.new(@role_serializer), @role_serializer, {}) - @spam_hash = FragmentCache.new(adapter.new(@spam_serializer), @spam_serializer, {}) - end - - def test_fragment_fetch_with_virtual_attributes - expected_result = { - id: @role.id, - description: @role.description, - slug: "#{@role.name}-#{@role.id}", - name: @role.name - } - assert_equal(@role_hash.fetch, expected_result) - end - - def test_fragment_fetch_with_namespaced_object - expected_result = { - id: @spam.id - } - assert_equal(@spam_hash.fetch, expected_result) - end - end -end diff --git a/test/cache_test.rb b/test/cache_test.rb index 283f35b8..57173d61 100644 --- a/test/cache_test.rb +++ b/test/cache_test.rb @@ -114,7 +114,7 @@ module ActiveModelSerializers def test_error_is_raised_if_cache_key_is_not_defined_on_object_or_passed_as_cache_option article = Article.new(title: 'Must Read') - e = assert_raises ActiveModelSerializers::CachedSerializer::UndefinedCacheKey do + e = assert_raises ActiveModel::Serializer::UndefinedCacheKey do render_object_with_cache(article) end assert_match(/ActiveModelSerializers::CacheTest::Article must define #cache_key, or the 'key:' option must be passed into 'CachedActiveModelSerializers_CacheTest_ArticleSerializer.cache'/, e.message) @@ -252,11 +252,11 @@ module ActiveModelSerializers attributes_serialization = serializable_alert.as_json assert_equal expected_cached_attributes, alert.attributes assert_equal alert.attributes, attributes_serialization - attributes_cache_key = CachedSerializer.new(serializable_alert.adapter.serializer).cache_key(serializable_alert.adapter) + attributes_cache_key = serializable_alert.adapter.serializer.cache_key(serializable_alert.adapter) assert_equal attributes_serialization, cache_store.fetch(attributes_cache_key) serializable_alert = serializable(alert, serializer: AlertSerializer, adapter: :json_api) - jsonapi_cache_key = CachedSerializer.new(serializable_alert.adapter.serializer).cache_key(serializable_alert.adapter) + jsonapi_cache_key = serializable_alert.adapter.serializer.cache_key(serializable_alert.adapter) # Assert cache keys differ refute_equal attributes_cache_key, jsonapi_cache_key # Assert (cached) serializations differ @@ -288,9 +288,9 @@ module ActiveModelSerializers serializable = ActiveModelSerializers::SerializableResource.new([@comment, @comment]) include_tree = ActiveModel::Serializer::IncludeTree.from_include_args('*') - actual = CachedSerializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_tree) + actual = ActiveModel::Serializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_tree) - assert_equal actual.size, 3 + assert_equal 3, actual.size assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cached_name}" } assert actual.any? { |key| key =~ %r{post/post-\d+} } assert actual.any? { |key| key =~ %r{author/author-\d+} } @@ -365,12 +365,109 @@ module ActiveModelSerializers assert called end + def test_cached_false_without_cache_store + cached_serializer = build_cached_serializer do |serializer| + serializer._cache = nil + end + refute cached_serializer.class.cache_enabled? + end + + def test_cached_true_with_cache_store_and_without_cache_only_and_cache_except + cached_serializer = build_cached_serializer do |serializer| + serializer._cache = Object + end + assert cached_serializer.class.cache_enabled? + end + + def test_cached_false_with_cache_store_and_with_cache_only + cached_serializer = build_cached_serializer do |serializer| + serializer._cache = Object + serializer._cache_only = [:name] + end + refute cached_serializer.class.cache_enabled? + end + + def test_cached_false_with_cache_store_and_with_cache_except + cached_serializer = build_cached_serializer do |serializer| + serializer._cache = Object + serializer._cache_except = [:content] + end + refute cached_serializer.class.cache_enabled? + end + + def test_fragment_cached_false_without_cache_store + cached_serializer = build_cached_serializer do |serializer| + serializer._cache = nil + serializer._cache_only = [:name] + end + refute cached_serializer.class.fragment_cache_enabled? + end + + def test_fragment_cached_true_with_cache_store_and_cache_only + cached_serializer = build_cached_serializer do |serializer| + serializer._cache = Object + serializer._cache_only = [:name] + end + assert cached_serializer.class.fragment_cache_enabled? + end + + def test_fragment_cached_true_with_cache_store_and_cache_except + cached_serializer = build_cached_serializer do |serializer| + serializer._cache = Object + serializer._cache_except = [:content] + end + assert cached_serializer.class.fragment_cache_enabled? + end + + def test_fragment_cached_false_with_cache_store_and_cache_except_and_cache_only + cached_serializer = build_cached_serializer do |serializer| + serializer._cache = Object + serializer._cache_except = [:content] + serializer._cache_only = [:name] + end + refute cached_serializer.class.fragment_cache_enabled? + end + + def test_fragment_fetch_with_virtual_attributes + @author = Author.new(name: 'Joao M. D. Moura') + @role = Role.new(name: 'Great Author', description: nil) + @role.author = [@author] + @role_serializer = RoleSerializer.new(@role) + @role_hash = @role_serializer.fetch_fragment_cache(ActiveModelSerializers::Adapter.configured_adapter.new(@role_serializer)) + + expected_result = { + id: @role.id, + description: @role.description, + slug: "#{@role.name}-#{@role.id}", + name: @role.name + } + assert_equal(@role_hash, expected_result) + end + + def test_fragment_fetch_with_namespaced_object + @spam = Spam::UnrelatedLink.new(id: 'spam-id-1') + @spam_serializer = Spam::UnrelatedLinkSerializer.new(@spam) + @spam_hash = @spam_serializer.fetch_fragment_cache(ActiveModelSerializers::Adapter.configured_adapter.new(@spam_serializer)) + expected_result = { + id: @spam.id + } + assert_equal(@spam_hash, expected_result) + end + private def cache_store ActiveModelSerializers.config.cache_store end + def build_cached_serializer + serializer = Class.new(ActiveModel::Serializer) + serializer._cache_key = nil + serializer._cache_options = nil + yield serializer if block_given? + serializer.new(Object) + end + def render_object_with_cache(obj, options = {}) @serializable_resource = serializable(obj, options) @serializable_resource.serializable_hash @@ -381,7 +478,7 @@ module ActiveModelSerializers end def cached_serialization(serializer) - cache_key = CachedSerializer.new(serializer).cache_key(adapter) + cache_key = serializer.cache_key(adapter) cache_store.fetch(cache_key) end end