From d0389ca765353add4b55d699a17452234ba42cd0 Mon Sep 17 00:00:00 2001 From: Logan Serman Date: Fri, 25 Mar 2016 16:24:43 -0500 Subject: [PATCH] Fix fragment caching inherited serializers to use distinct per-serializer caches. --- CHANGELOG.md | 1 + lib/active_model_serializers/fragment_cache.rb | 12 +++++++----- test/cache_test.rb | 18 ++++++++++++++++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 304707bb..ae32b219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Features: - [#1340](https://github.com/rails-api/active_model_serializers/pull/1340) Add support for resource-level meta. (@beauby) Fixes: +- [#1622](https://github.com/rails-api/active_model_serializers/pull/1622) Fix fragment caching inherited serializers to use distinct per-serializer caches. (@lserman) - [#1478](https://github.com/rails-api/active_model_serializers/pull/1478) Cache store will now be correctly set when serializers are loaded *before* Rails initializes. (@bf4) - [#1570](https://github.com/rails-api/active_model_serializers/pull/1570) Fixed pagination issue with last page size. (@bmorrall) diff --git a/lib/active_model_serializers/fragment_cache.rb b/lib/active_model_serializers/fragment_cache.rb index 425f147b..605da602 100644 --- a/lib/active_model_serializers/fragment_cache.rb +++ b/lib/active_model_serializers/fragment_cache.rb @@ -15,7 +15,7 @@ module ActiveModelSerializers object = serializer.object # It will split the serializer into two, one that will be cached and one that will not - serializers = fragment_serializer(object.class.name) + serializers = fragment_serializer # Get serializable hash from both cached_hash = serialize(object, serializers[:cached]) @@ -79,10 +79,12 @@ module ActiveModelSerializers # User_AdminCachedSerializer # User_AdminNonCachedSerializer # - def fragment_serializer(name) - klass = serializer.class - cached = "#{to_valid_const_name(name)}CachedSerializer" - non_cached = "#{to_valid_const_name(name)}NonCachedSerializer" + 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) diff --git a/test/cache_test.rb b/test/cache_test.rb index 46d3a973..c90b0b1d 100644 --- a/test/cache_test.rb +++ b/test/cache_test.rb @@ -1,6 +1,12 @@ require 'test_helper' require 'tmpdir' require 'tempfile' + +InheritedRoleSerializer = Class.new(RoleSerializer) do + cache key: 'inherited_role', only: [:name, :special_attribute] + attribute :special_attribute +end + module ActiveModelSerializers class CacheTest < ActiveSupport::TestCase def setup @@ -150,6 +156,14 @@ module ActiveModelSerializers assert_equal({ place: 'Nowhere' }, ActionController::Base.cache_store.fetch(@location.cache_key)) end + def test_fragment_cache_with_inheritance + inherited = render_object_with_cache(@role, serializer: InheritedRoleSerializer) + base = render_object_with_cache(@role) + + assert_includes(inherited.keys, :special_attribute) + refute_includes(base.keys, :special_attribute) + end + def test_uses_file_digest_in_cache_key render_object_with_cache(@blog) assert_equal(@blog_serializer.attributes, ActionController::Base.cache_store.fetch(@blog.cache_key_with_digest)) @@ -242,8 +256,8 @@ module ActiveModelSerializers private - def render_object_with_cache(obj) - ActiveModel::SerializableResource.new(obj).serializable_hash + def render_object_with_cache(obj, options = {}) + ActiveModel::SerializableResource.new(obj, options).serializable_hash end end end