mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-25 15:23:06 +00:00
Adding Fragment Cache to AMS
It's an upgrade based on the new Cache implementation #693. It allows to use the Rails conventions to cache specific attributes or associations. It's based on the Cache Composition implementation.
This commit is contained in:
78
lib/active_model/serializer/adapter/fragment_cache.rb
Normal file
78
lib/active_model/serializer/adapter/fragment_cache.rb
Normal file
@@ -0,0 +1,78 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
class Adapter
|
||||
class FragmentCache
|
||||
|
||||
attr_reader :serializer
|
||||
|
||||
def initialize(adapter, serializer, options, root)
|
||||
@root = root
|
||||
@options = options
|
||||
@adapter = adapter
|
||||
@serializer = serializer
|
||||
end
|
||||
|
||||
def fetch
|
||||
klass = serializer.class
|
||||
# It will split the serializer into two, one that will be cached and other wont
|
||||
serializers = fragment_serializer(serializer.object.class.name, klass)
|
||||
|
||||
# Instanciate 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, @options)
|
||||
non_cached_adapter = @adapter.class.new(non_cached_serializer, @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
|
||||
|
||||
private
|
||||
|
||||
def cached_attributes(klass, serializers)
|
||||
cached_attributes = (klass._cache_only) ? klass._cache_only : serializer.attributes.keys.delete_if {|attr| klass._cache_except.include?(attr) }
|
||||
non_cached_attributes = serializer.attributes.keys.delete_if {|attr| cached_attributes.include?(attr) }
|
||||
|
||||
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
|
||||
|
||||
def fragment_serializer(name, klass)
|
||||
cached = "#{name.capitalize}CachedSerializer"
|
||||
non_cached = "#{name.capitalize}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
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user