diff --git a/lib/active_model/serializer/adapter/base.rb b/lib/active_model/serializer/adapter/base.rb
index 46f0fea35..5563e9054 100644
--- a/lib/active_model/serializer/adapter/base.rb
+++ b/lib/active_model/serializer/adapter/base.rb
@@ -1,4 +1,3 @@
-require 'active_model/serializer/cached_serializer'
module ActiveModel
class Serializer
module Adapter
@@ -30,7 +29,7 @@ def fragment_cache(cached_hash, non_cached_hash)
end
def cache_check(serializer)
- ActiveModel::Serializer::CachedSerializer.new(serializer).cache_check(self) do
+ ActiveModelSerializers::CachedSerializer.new(serializer).cache_check(self) do
yield
end
end
diff --git a/lib/active_model/serializer/cached_serializer.rb b/lib/active_model/serializer/cached_serializer.rb
deleted file mode 100644
index a5eac9541..000000000
--- a/lib/active_model/serializer/cached_serializer.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require 'active_model/serializer/fragment_cache'
-module ActiveModel
- class Serializer
- class CachedSerializer
- def initialize(serializer)
- @cached_serializer = serializer
- @klass = @cached_serializer.class
- end
-
- def cache_check(adapter_instance)
- if cached?
- @klass._cache.fetch(cache_key, @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 && !@klass._cache_only && !@klass._cache_except
- end
-
- def fragment_cached?
- @klass._cache_only && !@klass._cache_except || !@klass._cache_only && @klass._cache_except
- end
-
- def cache_key
- parts = []
- parts << object_cache_key
- parts << @klass._cache_digest unless @klass._cache_options && @klass._cache_options[:skip_digest]
- parts.join('/')
- end
-
- def object_cache_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)
- (@klass._cache_key) ? "#{@klass._cache_key}/#{@cached_serializer.object.id}-#{object_time_safe}" : @cached_serializer.object.cache_key
- end
- end
- end
-end
diff --git a/lib/active_model/serializer/fragment_cache.rb b/lib/active_model/serializer/fragment_cache.rb
deleted file mode 100644
index 49185f625..000000000
--- a/lib/active_model/serializer/fragment_cache.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-module ActiveModel
- class Serializer
- class FragmentCache
- attr_reader :serializer
-
- def initialize(adapter, serializer, options)
- @instance_options = options
- @adapter = adapter
- @serializer = serializer
- end
-
- # TODO: Use Serializable::Resource
- # TODO: call +constantize+ less
- # 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
- klass = serializer.class
- # It will split the serializer into two, one that will be cached and one that will not
- serializers = fragment_serializer(serializer.object.class.name, klass)
-
- # Instantiate both serializers
- cached_serializer = serializers[:cached].constantize.new(serializer.object)
- non_cached_serializer = serializers[:non_cached].constantize.new(serializer.object)
-
- cached_adapter = adapter.class.new(cached_serializer, instance_options)
- non_cached_adapter = adapter.class.new(non_cached_serializer, instance_options)
-
- # Get serializable hash from both
- cached_hash = cached_adapter.serializable_hash
- non_cached_hash = non_cached_adapter.serializable_hash
-
- # Merge both results
- adapter.fragment_cache(cached_hash, non_cached_hash)
- end
-
- protected
-
- attr_reader :instance_options, :adapter
-
- private
-
- # Given a serializer class and 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 cached_attributes(klass, serializers)
- attributes = serializer.class._attributes
- cached_attributes = (klass._cache_only) ? klass._cache_only : attributes.reject { |attr| klass._cache_except.include?(attr) }
- non_cached_attributes = attributes - cached_attributes
-
- cached_attributes.each do |attribute|
- options = serializer.class._attributes_keys[attribute]
- options ||= {}
- # Add cached attributes to cached Serializer
- serializers[:cached].constantize.attribute(attribute, options)
- end
-
- non_cached_attributes.each do |attribute|
- options = serializer.class._attributes_keys[attribute]
- options ||= {}
- # Add non-cached attributes to non-cached Serializer
- serializers[:non_cached].constantize.attribute(attribute, options)
- end
- end
-
- # Given a resource name and its serializer's class
- # 1. Dyanmically 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).
- # User_AdminCachedSerializer
- # User_AdminNonCachedSerializer
- #
- def fragment_serializer(name, klass)
- cached = "#{to_valid_const_name(name)}CachedSerializer"
- non_cached = "#{to_valid_const_name(name)}NonCachedSerializer"
-
- Object.const_set cached, Class.new(ActiveModel::Serializer) unless Object.const_defined?(cached)
- Object.const_set non_cached, Class.new(ActiveModel::Serializer) unless Object.const_defined?(non_cached)
-
- klass._cache_options ||= {}
- klass._cache_options[:key] = klass._cache_key if klass._cache_key
-
- cached.constantize.cache(klass._cache_options)
-
- cached.constantize.fragmented(serializer)
- non_cached.constantize.fragmented(serializer)
-
- serializers = { cached: cached, non_cached: non_cached }
- cached_attributes(klass, serializers)
- serializers
- end
-
- def to_valid_const_name(name)
- name.gsub('::', '_')
- end
- end
- end
-end
diff --git a/lib/active_model_serializers.rb b/lib/active_model_serializers.rb
index d92823b5a..d62d63516 100644
--- a/lib/active_model_serializers.rb
+++ b/lib/active_model_serializers.rb
@@ -4,6 +4,8 @@
module ActiveModelSerializers
extend ActiveSupport::Autoload
autoload :Model
+ autoload :CachedSerializer
+ autoload :FragmentCache
autoload :Callbacks
autoload :Deserialization
autoload :Logging
diff --git a/lib/active_model_serializers/cached_serializer.rb b/lib/active_model_serializers/cached_serializer.rb
new file mode 100644
index 000000000..6b21fd8dc
--- /dev/null
+++ b/lib/active_model_serializers/cached_serializer.rb
@@ -0,0 +1,42 @@
+require 'active_model_serializers/fragment_cache'
+module ActiveModelSerializers
+ class CachedSerializer
+ def initialize(serializer)
+ @cached_serializer = serializer
+ @klass = @cached_serializer.class
+ end
+
+ def cache_check(adapter_instance)
+ if cached?
+ @klass._cache.fetch(cache_key, @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 && !@klass._cache_only && !@klass._cache_except
+ end
+
+ def fragment_cached?
+ @klass._cache_only && !@klass._cache_except || !@klass._cache_only && @klass._cache_except
+ end
+
+ def cache_key
+ parts = []
+ parts << object_cache_key
+ parts << @klass._cache_digest unless @klass._cache_options && @klass._cache_options[:skip_digest]
+ parts.join('/')
+ end
+
+ def object_cache_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)
+ (@klass._cache_key) ? "#{@klass._cache_key}/#{@cached_serializer.object.id}-#{object_time_safe}" : @cached_serializer.object.cache_key
+ end
+ end
+end
diff --git a/lib/active_model_serializers/fragment_cache.rb b/lib/active_model_serializers/fragment_cache.rb
new file mode 100644
index 000000000..627400465
--- /dev/null
+++ b/lib/active_model_serializers/fragment_cache.rb
@@ -0,0 +1,107 @@
+module ActiveModelSerializers
+ class FragmentCache
+ attr_reader :serializer
+
+ def initialize(adapter, serializer, options)
+ @instance_options = options
+ @adapter = adapter
+ @serializer = serializer
+ end
+
+ # TODO: Use Serializable::Resource
+ # TODO: call +constantize+ less
+ # 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
+ klass = serializer.class
+ # It will split the serializer into two, one that will be cached and one that will not
+ serializers = fragment_serializer(serializer.object.class.name, klass)
+
+ # Instantiate both serializers
+ cached_serializer = serializers[:cached].constantize.new(serializer.object)
+ non_cached_serializer = serializers[:non_cached].constantize.new(serializer.object)
+
+ cached_adapter = adapter.class.new(cached_serializer, instance_options)
+ non_cached_adapter = adapter.class.new(non_cached_serializer, instance_options)
+
+ # Get serializable hash from both
+ cached_hash = cached_adapter.serializable_hash
+ non_cached_hash = non_cached_adapter.serializable_hash
+
+ # Merge both results
+ adapter.fragment_cache(cached_hash, non_cached_hash)
+ end
+
+ protected
+
+ attr_reader :instance_options, :adapter
+
+ private
+
+ # Given a serializer class and 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 cached_attributes(klass, serializers)
+ attributes = serializer.class._attributes
+ cached_attributes = (klass._cache_only) ? klass._cache_only : attributes.reject { |attr| klass._cache_except.include?(attr) }
+ non_cached_attributes = attributes - cached_attributes
+
+ cached_attributes.each do |attribute|
+ options = serializer.class._attributes_keys[attribute]
+ options ||= {}
+ # Add cached attributes to cached Serializer
+ serializers[:cached].constantize.attribute(attribute, options)
+ end
+
+ non_cached_attributes.each do |attribute|
+ options = serializer.class._attributes_keys[attribute]
+ options ||= {}
+ # Add non-cached attributes to non-cached Serializer
+ serializers[:non_cached].constantize.attribute(attribute, options)
+ end
+ end
+
+ # Given a resource name and its serializer's class
+ # 1. Dyanmically 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).
+ # User_AdminCachedSerializer
+ # User_AdminNonCachedSerializer
+ #
+ def fragment_serializer(name, klass)
+ cached = "#{to_valid_const_name(name)}CachedSerializer"
+ non_cached = "#{to_valid_const_name(name)}NonCachedSerializer"
+
+ Object.const_set cached, Class.new(ActiveModel::Serializer) unless Object.const_defined?(cached)
+ Object.const_set non_cached, Class.new(ActiveModel::Serializer) unless Object.const_defined?(non_cached)
+
+ klass._cache_options ||= {}
+ klass._cache_options[:key] = klass._cache_key if klass._cache_key
+
+ cached.constantize.cache(klass._cache_options)
+
+ cached.constantize.fragmented(serializer)
+ non_cached.constantize.fragmented(serializer)
+
+ serializers = { cached: cached, non_cached: non_cached }
+ cached_attributes(klass, serializers)
+ serializers
+ end
+
+ def to_valid_const_name(name)
+ name.gsub('::', '_')
+ end
+ end
+end
diff --git a/test/serializers/fragment_cache_test.rb b/test/serializers/fragment_cache_test.rb
index f66def8c5..c0801176f 100644
--- a/test/serializers/fragment_cache_test.rb
+++ b/test/serializers/fragment_cache_test.rb
@@ -1,35 +1,33 @@
require 'test_helper'
-module ActiveModel
- class Serializer
- 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)
- @role_hash = FragmentCache.new(RoleSerializer.adapter.new(@role_serializer), @role_serializer, {})
- @spam_hash = FragmentCache.new(Spam::UnrelatedLinkSerializer.adapter.new(@spam_serializer), @spam_serializer, {})
- end
+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)
+ @role_hash = FragmentCache.new(RoleSerializer.adapter.new(@role_serializer), @role_serializer, {})
+ @spam_hash = FragmentCache.new(Spam::UnrelatedLinkSerializer.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_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
+ def test_fragment_fetch_with_namespaced_object
+ expected_result = {
+ id: @spam.id
+ }
+ assert_equal(@spam_hash.fetch, expected_result)
end
end
end