Refactor Association into Field like everything else (#1897)

* Make assocations asserts easier to understand

* Refactor Association into Field like everything else

* Make assocation serializer/links/meta lazier

* Push association deeper into relationship

* Simplify association usage in relationships

* Better naming of reflection parent serializer

* Easier to read association method
This commit is contained in:
Benjamin Fleischer
2016-08-31 08:35:41 -05:00
committed by L. Preston Sego III
parent 7d2997b3ff
commit 20e394d512
6 changed files with 94 additions and 47 deletions

View File

@@ -3,17 +3,32 @@ module ActiveModel
# This class hold all information about serializer's association.
#
# @attr [Symbol] name
# @attr [ActiveModel::Serializer] serializer
# @attr [Hash{Symbol => Object}] options
# @attr [block]
#
# @example
# Association.new(:comments, CommentSummarySerializer)
# Association.new(:comments, { serializer: CommentSummarySerializer })
#
Association = Struct.new(:name, :serializer, :options, :links, :meta) do
class Association < Field
# @return [Symbol]
def key
options.fetch(:key, name)
end
# @return [ActiveModel::Serializer, nil]
def serializer
options[:serializer]
end
# @return [Hash]
def links
options.fetch(:links) || {}
end
# @return [Hash, nil]
def meta
options[:meta]
end
end
end
end

View File

@@ -74,8 +74,8 @@ module ActiveModel
# @api private
#
def associate(reflection)
key = reflection.options[:key]
key ? self._reflections[key] = reflection : self._reflections[reflection.name] = reflection
key = reflection.options[:key] || reflection.name
self._reflections[key] = reflection
end
end

View File

@@ -88,7 +88,7 @@ module ActiveModel
# Build association. This method is used internally to
# build serializer's association by its reflection.
#
# @param [Serializer] subject is a parent serializer for given association
# @param [Serializer] parent_serializer for given association
# @param [Hash{Symbol => Object}] parent_serializer_options
#
# @example
@@ -106,17 +106,19 @@ module ActiveModel
#
# @api private
#
def build_association(subject, parent_serializer_options)
association_value = value(subject)
def build_association(parent_serializer, parent_serializer_options)
association_value = value(parent_serializer)
reflection_options = options.dup
serializer_class = subject.class.serializer_for(association_value, reflection_options)
serializer_class = parent_serializer.class.serializer_for(association_value, reflection_options)
reflection_options[:include_data] = @_include_data
reflection_options[:links] = @_links
reflection_options[:meta] = @_meta
if serializer_class
begin
serializer = serializer_class.new(
reflection_options[:serializer] = serializer_class.new(
association_value,
serializer_options(subject, parent_serializer_options, reflection_options)
serializer_options(parent_serializer, parent_serializer_options, reflection_options)
)
rescue ActiveModel::Serializer::CollectionSerializer::NoSerializerError
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
@@ -125,7 +127,8 @@ module ActiveModel
reflection_options[:virtual_value] = association_value
end
Association.new(name, serializer, reflection_options, @_links, @_meta)
block = nil
Association.new(name, reflection_options, block)
end
protected
@@ -134,12 +137,12 @@ module ActiveModel
private
def serializer_options(subject, parent_serializer_options, reflection_options)
def serializer_options(parent_serializer, parent_serializer_options, reflection_options)
serializer = reflection_options.fetch(:serializer, nil)
serializer_options = parent_serializer_options.except(:serializer)
serializer_options[:serializer] = serializer if serializer
serializer_options[:serializer_context_class] = subject.class
serializer_options[:serializer_context_class] = parent_serializer.class
serializer_options
end
end