From c2dccbac5f85332dba437342502fdae8fd44c7d7 Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Fri, 31 Mar 2017 13:09:51 -0500 Subject: [PATCH 1/2] Move attributes cache method out of concern --- lib/active_model/serializer.rb | 14 +++++++++-- .../serializer/concerns/caching.rb | 23 +++++++------------ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index ea24ce52..a9ecb1e3 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -379,8 +379,7 @@ module ActiveModel def serializable_hash(adapter_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance) adapter_options ||= {} options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options) - cached_attributes = adapter_options[:cached_attributes] ||= {} - resource = fetch_attributes(options[:fields], cached_attributes, adapter_instance) + resource = attributes_hash(adapter_options, options, adapter_instance) relationships = resource_relationships(adapter_options, options, adapter_instance) resource.merge(relationships) end @@ -412,6 +411,17 @@ module ActiveModel end end + # @api private + def attributes_hash(_adapter_options, options, adapter_instance) + if self.class.cache_enabled? + fetch_attributes(options[:fields], options[:cached_attributes] || {}, adapter_instance) + elsif self.class.fragment_cache_enabled? + fetch_attributes_fragment(adapter_instance, options[:cached_attributes] || {}) + else + attributes(options[:fields], true) + end + end + # @api private def resource_relationships(adapter_options, options, adapter_instance) relationships = {} diff --git a/lib/active_model/serializer/concerns/caching.rb b/lib/active_model/serializer/concerns/caching.rb index 3238adc8..69900001 100644 --- a/lib/active_model/serializer/concerns/caching.rb +++ b/lib/active_model/serializer/concerns/caching.rb @@ -170,6 +170,7 @@ module ActiveModel # Read cache from cache_store # @return [Hash] + # Used in CollectionSerializer to set :cached_attributes def cache_read_multi(collection_serializer, adapter_instance, include_directive) return {} if ActiveModelSerializers.config.cache_store.blank? @@ -215,23 +216,17 @@ module ActiveModel ### INSTANCE METHODS def fetch_attributes(fields, cached_attributes, adapter_instance) - if serializer_class.cache_enabled? - key = cache_key(adapter_instance) - cached_attributes.fetch(key) do - serializer_class.cache_store.fetch(key, serializer_class._cache_options) do - attributes(fields, true) - end + key = cache_key(adapter_instance) + cached_attributes.fetch(key) do + fetch(adapter_instance, serializer_class._cache_options, key) do + attributes(fields, true) end - elsif serializer_class.fragment_cache_enabled? - fetch_attributes_fragment(adapter_instance, cached_attributes) - else - attributes(fields, true) end end - def fetch(adapter_instance, cache_options = serializer_class._cache_options) + def fetch(adapter_instance, cache_options = serializer_class._cache_options, key = cache_key(adapter_instance)) if serializer_class.cache_store - serializer_class.cache_store.fetch(cache_key(adapter_instance), cache_options) do + serializer_class.cache_store.fetch(key, cache_options) do yield end else @@ -242,7 +237,6 @@ module ActiveModel # 1. Determine cached fields from serializer class options # 2. Get non_cached_fields and fetch cache_fields # 3. Merge the two hashes using adapter_instance#fragment_cache - # rubocop:disable Metrics/AbcSize def fetch_attributes_fragment(adapter_instance, cached_attributes = {}) serializer_class._cache_options ||= {} serializer_class._cache_options[:key] = serializer_class._cache_key if serializer_class._cache_key @@ -257,7 +251,7 @@ module ActiveModel key = cache_key(adapter_instance) cached_hash = cached_attributes.fetch(key) do - serializer_class.cache_store.fetch(key, serializer_class._cache_options) do + fetch(adapter_instance, serializer_class._cache_options, key) do hash = attributes(cached_fields, true) include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys) hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance) @@ -266,7 +260,6 @@ module ActiveModel # Merge both results adapter_instance.fragment_cache(cached_hash, non_cached_hash) end - # rubocop:enable Metrics/AbcSize def cache_key(adapter_instance) return @cache_key if defined?(@cache_key) From 6cd6ed7e78569373c27a7c76a99bdc9c6501e6c2 Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Fri, 31 Mar 2017 12:55:46 -0500 Subject: [PATCH 2/2] Move association serialization to association --- lib/active_model/serializer.rb | 23 +++---------------- lib/active_model/serializer/association.rb | 16 +++++++++++++ .../serializer/concerns/caching.rb | 4 ++-- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index a9ecb1e3..6e1d4bfe 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -380,7 +380,7 @@ module ActiveModel adapter_options ||= {} options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options) resource = attributes_hash(adapter_options, options, adapter_instance) - relationships = resource_relationships(adapter_options, options, adapter_instance) + relationships = associations_hash(adapter_options, options, adapter_instance) resource.merge(relationships) end alias to_hash serializable_hash @@ -423,34 +423,17 @@ module ActiveModel end # @api private - def resource_relationships(adapter_options, options, adapter_instance) + def associations_hash(adapter_options, options, adapter_instance) relationships = {} include_directive = options.fetch(:include_directive) associations(include_directive).each do |association| adapter_opts = adapter_options.merge(include_directive: include_directive[association.key]) - relationships[association.key] ||= relationship_value_for(association, adapter_opts, adapter_instance) + relationships[association.key] ||= association.serializable_hash(adapter_opts, adapter_instance) end relationships end - # @api private - def relationship_value_for(association, adapter_options, adapter_instance) - return association.options[:virtual_value] if association.options[:virtual_value] - association_serializer = association.serializer - association_object = association_serializer && association_serializer.object - return unless association_object - - relationship_value = association_serializer.serializable_hash(adapter_options, {}, adapter_instance) - - if association.options[:polymorphic] && relationship_value - polymorphic_type = association_object.class.name.underscore - relationship_value = { type: polymorphic_type, polymorphic_type.to_sym => relationship_value } - end - - relationship_value - end - protected attr_accessor :instance_options diff --git a/lib/active_model/serializer/association.rb b/lib/active_model/serializer/association.rb index b2e18392..459a8186 100644 --- a/lib/active_model/serializer/association.rb +++ b/lib/active_model/serializer/association.rb @@ -29,6 +29,22 @@ module ActiveModel def meta options[:meta] end + + # @api private + def serializable_hash(adapter_options, adapter_instance) + return options[:virtual_value] if options[:virtual_value] + object = serializer && serializer.object + return unless object + + serialization = serializer.serializable_hash(adapter_options, {}, adapter_instance) + + if options[:polymorphic] && serialization + polymorphic_type = object.class.name.underscore + serialization = { type: polymorphic_type, polymorphic_type.to_sym => serialization } + end + + serialization + end end end end diff --git a/lib/active_model/serializer/concerns/caching.rb b/lib/active_model/serializer/concerns/caching.rb index 69900001..f4c72468 100644 --- a/lib/active_model/serializer/concerns/caching.rb +++ b/lib/active_model/serializer/concerns/caching.rb @@ -245,7 +245,7 @@ module ActiveModel non_cached_fields = fields[:non_cached].dup non_cached_hash = attributes(non_cached_fields, true) include_directive = JSONAPI::IncludeDirective.new(non_cached_fields - non_cached_hash.keys) - non_cached_hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance) + non_cached_hash.merge! associations_hash({}, { include_directive: include_directive }, adapter_instance) cached_fields = fields[:cached].dup key = cache_key(adapter_instance) @@ -254,7 +254,7 @@ module ActiveModel fetch(adapter_instance, serializer_class._cache_options, key) do hash = attributes(cached_fields, true) include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys) - hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance) + hash.merge! associations_hash({}, { include_directive: include_directive }, adapter_instance) end end # Merge both results