mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-25 15:23:06 +00:00
Distinguish options ivar from local; Extract latent Adapter::CachedSerializer
This commit is contained in:
@@ -10,6 +10,7 @@ module ActiveModel
|
||||
autoload :JsonApi
|
||||
autoload :Null
|
||||
autoload :FlattenJson
|
||||
autoload :CachedSerializer
|
||||
|
||||
def self.create(resource, options = {})
|
||||
override = options.delete(:adapter)
|
||||
@@ -80,11 +81,11 @@ module ActiveModel
|
||||
ActiveModel::Serializer::Adapter.register(subclass.to_s.demodulize, subclass)
|
||||
end
|
||||
|
||||
attr_reader :serializer
|
||||
attr_reader :serializer, :instance_options
|
||||
|
||||
def initialize(serializer, options = {})
|
||||
@serializer = serializer
|
||||
@options = options
|
||||
@instance_options = options
|
||||
end
|
||||
|
||||
def serializable_hash(options = nil)
|
||||
@@ -101,43 +102,12 @@ module ActiveModel
|
||||
raise NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cache_check(serializer)
|
||||
@cached_serializer = serializer
|
||||
@klass = @cached_serializer.class
|
||||
if is_cached?
|
||||
@klass._cache.fetch(cache_key, @klass._cache_options) do
|
||||
yield
|
||||
end
|
||||
elsif is_fragment_cached?
|
||||
FragmentCache.new(self, @cached_serializer, @options).fetch
|
||||
else
|
||||
CachedSerializer.new(serializer).cache_check(self) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def is_cached?
|
||||
@klass._cache && !@klass._cache_only && !@klass._cache_except
|
||||
end
|
||||
|
||||
def is_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
|
||||
|
||||
def meta
|
||||
serializer.meta if serializer.respond_to?(:meta)
|
||||
end
|
||||
|
||||
45
lib/active_model/serializer/adapter/cached_serializer.rb
Normal file
45
lib/active_model/serializer/adapter/cached_serializer.rb
Normal file
@@ -0,0 +1,45 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
class Adapter
|
||||
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
|
||||
end
|
||||
@@ -2,7 +2,7 @@ class ActiveModel::Serializer::Adapter::FragmentCache
|
||||
attr_reader :serializer
|
||||
|
||||
def initialize(adapter, serializer, options)
|
||||
@options = options
|
||||
@instance_options = options
|
||||
@adapter = adapter
|
||||
@serializer = serializer
|
||||
end
|
||||
@@ -16,19 +16,23 @@ class ActiveModel::Serializer::Adapter::FragmentCache
|
||||
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)
|
||||
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)
|
||||
adapter.fragment_cache(cached_hash, non_cached_hash)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
ActiveModelSerializers.silence_warnings do
|
||||
attr_reader :instance_options, :adapter
|
||||
end
|
||||
|
||||
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) }
|
||||
|
||||
@@ -15,13 +15,13 @@ class ActiveModel::Serializer::Adapter::Json < ActiveModel::Serializer::Adapter
|
||||
|
||||
serializer.associations.each do |association|
|
||||
serializer = association.serializer
|
||||
opts = association.options
|
||||
association_options = association.options
|
||||
|
||||
if serializer.respond_to?(:each)
|
||||
array_serializer = serializer
|
||||
hash[association.key] = array_serializer.map do |item|
|
||||
cache_check(item) do
|
||||
item.attributes(opts)
|
||||
item.attributes(association_options)
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -30,8 +30,8 @@ class ActiveModel::Serializer::Adapter::Json < ActiveModel::Serializer::Adapter
|
||||
cache_check(serializer) do
|
||||
serializer.attributes(options)
|
||||
end
|
||||
elsif opts[:virtual_value]
|
||||
opts[:virtual_value]
|
||||
elsif association_options[:virtual_value]
|
||||
association_options[:virtual_value]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class ActiveModel::Serializer::Adapter::JsonApi < ActiveModel::Serializer::Adapt
|
||||
|
||||
def initialize(serializer, options = {})
|
||||
super
|
||||
@included = ActiveModel::Serializer::Utils.include_args_to_hash(@options[:include])
|
||||
@included = ActiveModel::Serializer::Utils.include_args_to_hash(instance_options[:include])
|
||||
fields = options.delete(:fields)
|
||||
if fields
|
||||
@fieldset = ActiveModel::Serializer::Fieldset.new(fields, serializer.json_key)
|
||||
@@ -24,16 +24,20 @@ class ActiveModel::Serializer::Adapter::JsonApi < ActiveModel::Serializer::Adapt
|
||||
end
|
||||
|
||||
def fragment_cache(cached_hash, non_cached_hash)
|
||||
root = false if @options.include?(:include)
|
||||
root = false if instance_options.include?(:include)
|
||||
ActiveModel::Serializer::Adapter::JsonApi::FragmentCache.new.fragment_cache(root, cached_hash, non_cached_hash)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
ActiveModel.silence_warnings do
|
||||
attr_reader :included, :fieldset
|
||||
end
|
||||
|
||||
def serializable_hash_for_collection(serializer, options)
|
||||
hash = { data: [] }
|
||||
serializer.each do |s|
|
||||
result = self.class.new(s, @options.merge(fieldset: @fieldset)).serializable_hash(options)
|
||||
result = self.class.new(s, instance_options.merge(fieldset: fieldset)).serializable_hash(options)
|
||||
hash[:data] << result[:data]
|
||||
|
||||
if result[:included]
|
||||
@@ -85,7 +89,7 @@ class ActiveModel::Serializer::Adapter::JsonApi < ActiveModel::Serializer::Adapt
|
||||
end
|
||||
|
||||
def resource_object_for(serializer, options = {})
|
||||
options[:fields] = @fieldset && @fieldset.fields_for(serializer)
|
||||
options[:fields] = fieldset && fieldset.fields_for(serializer)
|
||||
|
||||
cache_check(serializer) do
|
||||
result = resource_identifier_for(serializer)
|
||||
@@ -120,12 +124,10 @@ class ActiveModel::Serializer::Adapter::JsonApi < ActiveModel::Serializer::Adapt
|
||||
end
|
||||
|
||||
def included_for(serializer)
|
||||
included = @included.flat_map do |inc|
|
||||
included.flat_map { |inc|
|
||||
association = serializer.associations.find { |assoc| assoc.key == inc.first }
|
||||
_included_for(association.serializer, inc.second) if association
|
||||
end
|
||||
|
||||
included.uniq
|
||||
}.uniq
|
||||
end
|
||||
|
||||
def _included_for(serializer, includes)
|
||||
@@ -134,7 +136,7 @@ class ActiveModel::Serializer::Adapter::JsonApi < ActiveModel::Serializer::Adapt
|
||||
else
|
||||
return [] unless serializer && serializer.object
|
||||
|
||||
primary_data = primary_data_for(serializer, @options)
|
||||
primary_data = primary_data_for(serializer, instance_options)
|
||||
relationships = relationships_for(serializer)
|
||||
primary_data[:relationships] = relationships if relationships.any?
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ module ActiveModel
|
||||
end
|
||||
|
||||
def json_key
|
||||
key = root || @serializers.first.try(:json_key) || object.try(:name).try(:underscore)
|
||||
key = root || serializers.first.try(:json_key) || object.try(:name).try(:underscore)
|
||||
key.try(:pluralize)
|
||||
end
|
||||
|
||||
@@ -35,6 +35,12 @@ module ActiveModel
|
||||
object.respond_to?(:total_pages) &&
|
||||
object.respond_to?(:size)
|
||||
end
|
||||
|
||||
private # rubocop:disable Lint/UselessAccessModifier
|
||||
|
||||
ActiveModelSerializers.silence_warnings do
|
||||
attr_reader :serializers
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -88,7 +88,7 @@ module ActiveModel
|
||||
|
||||
Enumerator.new do |y|
|
||||
self.class._reflections.each do |reflection|
|
||||
y.yield reflection.build_association(self, options)
|
||||
y.yield reflection.build_association(self, instance_options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,7 +26,7 @@ module ActiveModel
|
||||
raw_fields.inject({}) { |h, (k, v)| h[k.to_sym] = v.map(&:to_sym); h }
|
||||
elsif raw_fields.is_a?(Array)
|
||||
if root.nil?
|
||||
raise ArgumentError, 'The root argument must be specified if the fields argument is an array.'
|
||||
raise ArgumentError, 'The root argument must be specified if the fields argument is an array.'.freeze
|
||||
end
|
||||
hash = {}
|
||||
hash[root.to_sym] = raw_fields.map(&:to_sym)
|
||||
|
||||
Reference in New Issue
Block a user