From 7254d34c9082c8a1d6b22224d87d4e81ba291467 Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Sun, 5 Jun 2016 23:01:21 -0500 Subject: [PATCH] Move Serializer#serialize into Serializer#serializable_hash --- lib/active_model/serializer.rb | 27 ++++------ .../serializer/collection_serializer.rb | 50 +++++++++++-------- .../adapter/attributes.rb | 2 +- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index b2884b9c..570073c7 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -109,6 +109,7 @@ module ActiveModel end end + # @api private def self.serialization_adapter_instance @serialization_adapter_instance ||= ActiveModelSerializers::Adapter::Attributes end @@ -138,9 +139,7 @@ module ActiveModel # associations, similar to how ActiveModel::Serializers::JSON is used # in ActiveRecord::Base. # - # TODO: Move to here the Attributes adapter logic for - # +serializable_hash_for_single_resource(options)+ - # and include ActiveModel::Serializers::JSON. + # TODO: Include ActiveModel::Serializers::JSON. # So that the below is true: # @param options [nil, Hash] The same valid options passed to `serializable_hash` # (:only, :except, :methods, and :include). @@ -164,10 +163,13 @@ module ActiveModel # serializer.as_json(include: :posts) # # Second level and higher order associations work as well: # serializer.as_json(include: { posts: { include: { comments: { only: :body } }, only: :title } }) - def serializable_hash(adapter_opts = nil) - adapter_opts ||= {} - adapter_opts = { include: '*' }.merge!(adapter_opts) - serialize(adapter_opts) + 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 = cached_attributes(options[:fields], cached_attributes, adapter_instance) + relationships = resource_relationships(adapter_options, options, adapter_instance) + resource.merge(relationships) end alias to_hash serializable_hash alias to_h serializable_hash @@ -199,15 +201,6 @@ module ActiveModel end end - # @api private - def serialize(adapter_options, options = {}, adapter_instance = self.class.serialization_adapter_instance) - options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options) - cached_attributes = adapter_options[:cached_attributes] ||= {} - resource = cached_attributes(options[:fields], cached_attributes, adapter_instance) - relationships = resource_relationships(adapter_options, options, adapter_instance) - resource.merge(relationships) - end - # @api private def resource_relationships(adapter_options, options, adapter_instance) relationships = {} @@ -227,7 +220,7 @@ module ActiveModel association_object = association_serializer && association_serializer.object return unless association_object - relationship_value = association_serializer.serialize(adapter_options, {}, adapter_instance) + relationship_value = association_serializer.serializable_hash(adapter_options, {}, adapter_instance) if association.options[:polymorphic] && relationship_value polymorphic_type = association_object.class.name.underscore diff --git a/lib/active_model/serializer/collection_serializer.rb b/lib/active_model/serializer/collection_serializer.rb index a2367195..bb84644c 100644 --- a/lib/active_model/serializer/collection_serializer.rb +++ b/lib/active_model/serializer/collection_serializer.rb @@ -11,22 +11,23 @@ module ActiveModel @object = resources @options = options @root = options[:root] - serializer_context_class = options.fetch(:serializer_context_class, ActiveModel::Serializer) - @serializers = resources.map do |resource| - serializer_class = options.fetch(:serializer) { serializer_context_class.serializer_for(resource) } - - if serializer_class.nil? # rubocop:disable Style/GuardClause - fail NoSerializerError, "No serializer found for resource: #{resource.inspect}" - else - serializer_class.new(resource, options.except(:serializer)) - end - end + @serializers = serializers_from_resources end def success? true end + # @api private + def serializable_hash(adapter_options, options, adapter_instance) + include_directive = ActiveModel::Serializer.include_directive_from_options(adapter_options) + adapter_options[:cached_attributes] ||= ActiveModel::Serializer.cache_read_multi(self, adapter_instance, include_directive) + adapter_opts = adapter_options.merge(include_directive: include_directive) + serializers.map do |serializer| + serializer.serializable_hash(adapter_opts, options, adapter_instance) + end + end + # TODO: unify naming of root, json_key, and _type. Right now, a serializer's # json_key comes from the root option or the object's model name, by default. # But, if a dev defines a custom `json_key` method with an explicit value, @@ -56,19 +57,28 @@ module ActiveModel object.respond_to?(:size) end - # @api private - def serialize(adapter_options, options, adapter_instance) - include_directive = ActiveModel::Serializer.include_directive_from_options(adapter_options) - adapter_options[:cached_attributes] ||= ActiveModel::Serializer.cache_read_multi(self, adapter_instance, include_directive) - adapter_opts = adapter_options.merge(include_directive: include_directive) - serializers.map do |serializer| - serializer.serialize(adapter_opts, options, adapter_instance) - end - end - protected attr_reader :serializers, :options + + private + + def serializers_from_resources + serializer_context_class = options.fetch(:serializer_context_class, ActiveModel::Serializer) + object.map do |resource| + serializer_from_resource(resource, serializer_context_class, options) + end + end + + def serializer_from_resource(resource, serializer_context_class, options) + serializer_class = options.fetch(:serializer) { serializer_context_class.serializer_for(resource) } + + if serializer_class.nil? # rubocop:disable Style/GuardClause + fail NoSerializerError, "No serializer found for resource: #{resource.inspect}" + else + serializer_class.new(resource, options.except(:serializer)) + end + end end end end diff --git a/lib/active_model_serializers/adapter/attributes.rb b/lib/active_model_serializers/adapter/attributes.rb index 3d2e7b52..f28295c0 100644 --- a/lib/active_model_serializers/adapter/attributes.rb +++ b/lib/active_model_serializers/adapter/attributes.rb @@ -3,7 +3,7 @@ module ActiveModelSerializers class Attributes < Base def serializable_hash(options = nil) options = serialization_options(options) - serializer.serialize(instance_options, options, self) + serializer.serializable_hash(instance_options, options, self) end end end