mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-22 22:06:50 +00:00
Merge pull request #2026 from bf4/refactor_association
Refactor Association to make it eval reflection JIT
This commit is contained in:
commit
0f59d64ed5
@ -332,18 +332,17 @@ module ActiveModel
|
|||||||
# @param [JSONAPI::IncludeDirective] include_directive (defaults to the
|
# @param [JSONAPI::IncludeDirective] include_directive (defaults to the
|
||||||
# +default_include_directive+ config value when not provided)
|
# +default_include_directive+ config value when not provided)
|
||||||
# @return [Enumerator<Association>]
|
# @return [Enumerator<Association>]
|
||||||
#
|
|
||||||
def associations(include_directive = ActiveModelSerializers.default_include_directive, include_slice = nil)
|
def associations(include_directive = ActiveModelSerializers.default_include_directive, include_slice = nil)
|
||||||
include_slice ||= include_directive
|
include_slice ||= include_directive
|
||||||
return unless object
|
return Enumerator.new unless object
|
||||||
|
|
||||||
Enumerator.new do |y|
|
Enumerator.new do |y|
|
||||||
self.class._reflections.values.each do |reflection|
|
self.class._reflections.each do |key, reflection|
|
||||||
next if reflection.excluded?(self)
|
next if reflection.excluded?(self)
|
||||||
key = reflection.options.fetch(:key, reflection.name)
|
|
||||||
next unless include_directive.key?(key)
|
next unless include_directive.key?(key)
|
||||||
|
|
||||||
y.yield reflection.build_association(self, instance_options, include_slice)
|
association = reflection.build_association(self, instance_options, include_slice)
|
||||||
|
y.yield association
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -351,31 +350,6 @@ module ActiveModel
|
|||||||
# @return [Hash] containing the attributes and first level
|
# @return [Hash] containing the attributes and first level
|
||||||
# associations, similar to how ActiveModel::Serializers::JSON is used
|
# associations, similar to how ActiveModel::Serializers::JSON is used
|
||||||
# in ActiveRecord::Base.
|
# in ActiveRecord::Base.
|
||||||
#
|
|
||||||
# TODO: Include <tt>ActiveModel::Serializers::JSON</tt>.
|
|
||||||
# So that the below is true:
|
|
||||||
# @param options [nil, Hash] The same valid options passed to `serializable_hash`
|
|
||||||
# (:only, :except, :methods, and :include).
|
|
||||||
#
|
|
||||||
# See
|
|
||||||
# https://github.com/rails/rails/blob/v5.0.0.beta2/activemodel/lib/active_model/serializers/json.rb#L17-L101
|
|
||||||
# https://github.com/rails/rails/blob/v5.0.0.beta2/activemodel/lib/active_model/serialization.rb#L85-L123
|
|
||||||
# https://github.com/rails/rails/blob/v5.0.0.beta2/activerecord/lib/active_record/serialization.rb#L11-L17
|
|
||||||
# https://github.com/rails/rails/blob/v5.0.0.beta2/activesupport/lib/active_support/core_ext/object/json.rb#L147-L162
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
# # The :only and :except options can be used to limit the attributes included, and work
|
|
||||||
# # similar to the attributes method.
|
|
||||||
# serializer.as_json(only: [:id, :name])
|
|
||||||
# serializer.as_json(except: [:id, :created_at, :age])
|
|
||||||
#
|
|
||||||
# # To include the result of some method calls on the model use :methods:
|
|
||||||
# serializer.as_json(methods: :permalink)
|
|
||||||
#
|
|
||||||
# # To include associations use :include:
|
|
||||||
# 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_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance)
|
def serializable_hash(adapter_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance)
|
||||||
adapter_options ||= {}
|
adapter_options ||= {}
|
||||||
options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
|
options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
|
||||||
@ -387,13 +361,6 @@ module ActiveModel
|
|||||||
alias to_h serializable_hash
|
alias to_h serializable_hash
|
||||||
|
|
||||||
# @see #serializable_hash
|
# @see #serializable_hash
|
||||||
# TODO: When moving attributes adapter logic here, @see #serializable_hash
|
|
||||||
# So that the below is true:
|
|
||||||
# @param options [nil, Hash] The same valid options passed to `as_json`
|
|
||||||
# (:root, :only, :except, :methods, and :include).
|
|
||||||
# The default for `root` is nil.
|
|
||||||
# The default value for include_root is false. You can change it to true if the given
|
|
||||||
# JSON string includes a single root node.
|
|
||||||
def as_json(adapter_opts = nil)
|
def as_json(adapter_opts = nil)
|
||||||
serializable_hash(adapter_opts)
|
serializable_hash(adapter_opts)
|
||||||
end
|
end
|
||||||
@ -424,14 +391,12 @@ module ActiveModel
|
|||||||
|
|
||||||
# @api private
|
# @api private
|
||||||
def associations_hash(adapter_options, options, adapter_instance)
|
def associations_hash(adapter_options, options, adapter_instance)
|
||||||
relationships = {}
|
|
||||||
include_directive = options.fetch(:include_directive)
|
include_directive = options.fetch(:include_directive)
|
||||||
associations(include_directive).each do |association|
|
include_slice = options[:include_slice]
|
||||||
adapter_opts = adapter_options.merge(include_directive: include_directive[association.key])
|
associations(include_directive, include_slice).each_with_object({}) do |association, relationships|
|
||||||
relationships[association.key] ||= association.serializable_hash(adapter_opts, adapter_instance)
|
adapter_opts = adapter_options.merge(include_directive: include_directive[association.key], adapter_instance: adapter_instance)
|
||||||
|
relationships[association.key] = association.serializable_hash(adapter_opts, adapter_instance)
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|||||||
@ -1,50 +1,67 @@
|
|||||||
|
require 'active_model/serializer/lazy_association'
|
||||||
|
|
||||||
module ActiveModel
|
module ActiveModel
|
||||||
class Serializer
|
class Serializer
|
||||||
# This class holds all information about serializer's association.
|
# This class holds all information about serializer's association.
|
||||||
#
|
#
|
||||||
# @attr [Symbol] name
|
# @api private
|
||||||
# @attr [Hash{Symbol => Object}] options
|
Association = Struct.new(:reflection, :association_options) do
|
||||||
# @attr [block]
|
attr_reader :lazy_association
|
||||||
#
|
delegate :object, :include_data?, :virtual_value, :collection?, to: :lazy_association
|
||||||
# @example
|
|
||||||
# Association.new(:comments, { serializer: CommentSummarySerializer })
|
def initialize(*)
|
||||||
#
|
super
|
||||||
class Association < Field
|
@lazy_association = LazyAssociation.new(reflection, association_options)
|
||||||
# @return [Symbol]
|
|
||||||
def key
|
|
||||||
options.fetch(:key, name)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ActiveModel::Serializer, nil]
|
# @return [Symbol]
|
||||||
def serializer
|
delegate :name, to: :reflection
|
||||||
options[:serializer]
|
|
||||||
|
# @return [Symbol]
|
||||||
|
def key
|
||||||
|
reflection_options.fetch(:key, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [True,False]
|
||||||
|
def key?
|
||||||
|
reflection_options.key?(:key)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Hash]
|
# @return [Hash]
|
||||||
def links
|
def links
|
||||||
options.fetch(:links) || {}
|
reflection_options.fetch(:links) || {}
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Hash, nil]
|
# @return [Hash, nil]
|
||||||
|
# This gets mutated, so cannot use the cached reflection_options
|
||||||
def meta
|
def meta
|
||||||
options[:meta]
|
reflection.options[:meta]
|
||||||
|
end
|
||||||
|
|
||||||
|
def polymorphic?
|
||||||
|
true == reflection_options[:polymorphic]
|
||||||
end
|
end
|
||||||
|
|
||||||
# @api private
|
# @api private
|
||||||
def serializable_hash(adapter_options, adapter_instance)
|
def serializable_hash(adapter_options, adapter_instance)
|
||||||
return options[:virtual_value] if options[:virtual_value]
|
association_serializer = lazy_association.serializer
|
||||||
object = serializer && serializer.object
|
return virtual_value if virtual_value
|
||||||
return unless object
|
association_object = association_serializer && association_serializer.object
|
||||||
|
return unless association_object
|
||||||
|
|
||||||
serialization = serializer.serializable_hash(adapter_options, {}, adapter_instance)
|
serialization = association_serializer.serializable_hash(adapter_options, {}, adapter_instance)
|
||||||
|
|
||||||
if options[:polymorphic] && serialization
|
if polymorphic? && serialization
|
||||||
polymorphic_type = object.class.name.underscore
|
polymorphic_type = association_object.class.name.underscore
|
||||||
serialization = { type: polymorphic_type, polymorphic_type.to_sym => serialization }
|
serialization = { type: polymorphic_type, polymorphic_type.to_sym => serialization }
|
||||||
end
|
end
|
||||||
|
|
||||||
serialization
|
serialization
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
delegate :reflection_options, to: :lazy_association
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
module ActiveModel
|
module ActiveModel
|
||||||
class Serializer
|
class Serializer
|
||||||
# @api private
|
# @api private
|
||||||
class BelongsToReflection < SingularReflection
|
class BelongsToReflection < Reflection
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
module ActiveModel
|
|
||||||
class Serializer
|
|
||||||
# @api private
|
|
||||||
class CollectionReflection < Reflection
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -193,12 +193,14 @@ module ActiveModel
|
|||||||
cache_keys << object_cache_key(serializer, adapter_instance)
|
cache_keys << object_cache_key(serializer, adapter_instance)
|
||||||
|
|
||||||
serializer.associations(include_directive).each do |association|
|
serializer.associations(include_directive).each do |association|
|
||||||
if association.serializer.respond_to?(:each)
|
# TODO(BF): Process relationship without evaluating lazy_association
|
||||||
association.serializer.each do |sub_serializer|
|
association_serializer = association.lazy_association.serializer
|
||||||
|
if association_serializer.respond_to?(:each)
|
||||||
|
association_serializer.each do |sub_serializer|
|
||||||
cache_keys << object_cache_key(sub_serializer, adapter_instance)
|
cache_keys << object_cache_key(sub_serializer, adapter_instance)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
cache_keys << object_cache_key(association.serializer, adapter_instance)
|
cache_keys << object_cache_key(association_serializer, adapter_instance)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
module ActiveModel
|
module ActiveModel
|
||||||
class Serializer
|
class Serializer
|
||||||
# @api private
|
# @api private
|
||||||
class HasManyReflection < CollectionReflection
|
class HasManyReflection < Reflection
|
||||||
|
def collection?
|
||||||
|
true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
module ActiveModel
|
module ActiveModel
|
||||||
class Serializer
|
class Serializer
|
||||||
# @api private
|
# @api private
|
||||||
class HasOneReflection < SingularReflection
|
class HasOneReflection < Reflection
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
95
lib/active_model/serializer/lazy_association.rb
Normal file
95
lib/active_model/serializer/lazy_association.rb
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
module ActiveModel
|
||||||
|
class Serializer
|
||||||
|
# @api private
|
||||||
|
LazyAssociation = Struct.new(:reflection, :association_options) do
|
||||||
|
REFLECTION_OPTIONS = %i(key links polymorphic meta serializer virtual_value namespace).freeze
|
||||||
|
|
||||||
|
delegate :collection?, to: :reflection
|
||||||
|
|
||||||
|
def reflection_options
|
||||||
|
@reflection_options ||= reflection.options.dup.reject { |k, _| !REFLECTION_OPTIONS.include?(k) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def object
|
||||||
|
@object ||= reflection.value(
|
||||||
|
association_options.fetch(:parent_serializer),
|
||||||
|
association_options.fetch(:include_slice)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
alias_method :eval_reflection_block, :object
|
||||||
|
|
||||||
|
def include_data?
|
||||||
|
eval_reflection_block if reflection.block
|
||||||
|
reflection.include_data?(
|
||||||
|
association_options.fetch(:include_slice)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ActiveModel::Serializer, nil]
|
||||||
|
def serializer
|
||||||
|
return @serializer if defined?(@serializer)
|
||||||
|
if serializer_class
|
||||||
|
serialize_object!(object)
|
||||||
|
elsif !object.nil? && !object.instance_of?(Object)
|
||||||
|
cached_result[:virtual_value] = object
|
||||||
|
end
|
||||||
|
@serializer = cached_result[:serializer]
|
||||||
|
end
|
||||||
|
|
||||||
|
def virtual_value
|
||||||
|
cached_result[:virtual_value] || reflection_options[:virtual_value]
|
||||||
|
end
|
||||||
|
|
||||||
|
def serializer_class
|
||||||
|
return @serializer_class if defined?(@serializer_class)
|
||||||
|
serializer_for_options = { namespace: namespace }
|
||||||
|
serializer_for_options[:serializer] = reflection_options[:serializer] if reflection_options.key?(:serializer)
|
||||||
|
@serializer_class = association_options.fetch(:parent_serializer).class.serializer_for(object, serializer_for_options)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def cached_result
|
||||||
|
@cached_result ||= {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def serialize_object!(object)
|
||||||
|
if collection?
|
||||||
|
if (serializer = instantiate_collection_serializer(object)).nil?
|
||||||
|
# BUG: per #2027, JSON API resource relationships are only id and type, and hence either
|
||||||
|
# *require* a serializer or we need to be a little clever about figuring out the id/type.
|
||||||
|
# In either case, returning the raw virtual value will almost always be incorrect.
|
||||||
|
#
|
||||||
|
# Should be reflection_options[:virtual_value] or adapter needs to figure out what to do
|
||||||
|
# with an object that is non-nil and has no defined serializer.
|
||||||
|
cached_result[:virtual_value] = object.try(:as_json) || object
|
||||||
|
else
|
||||||
|
cached_result[:serializer] = serializer
|
||||||
|
end
|
||||||
|
else
|
||||||
|
cached_result[:serializer] = instantiate_serializer(object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def instantiate_serializer(object)
|
||||||
|
serializer_options = association_options.fetch(:parent_serializer_options).except(:serializer)
|
||||||
|
serializer_options[:serializer_context_class] = association_options.fetch(:parent_serializer).class
|
||||||
|
serializer = reflection_options.fetch(:serializer, nil)
|
||||||
|
serializer_options[:serializer] = serializer if serializer
|
||||||
|
serializer_class.new(object, serializer_options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def instantiate_collection_serializer(object)
|
||||||
|
serializer = catch(:no_serializer) do
|
||||||
|
instantiate_serializer(object)
|
||||||
|
end
|
||||||
|
serializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def namespace
|
||||||
|
reflection_options[:namespace] ||
|
||||||
|
association_options.fetch(:parent_serializer_options)[:namespace]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,4 +1,5 @@
|
|||||||
require 'active_model/serializer/field'
|
require 'active_model/serializer/field'
|
||||||
|
require 'active_model/serializer/association'
|
||||||
|
|
||||||
module ActiveModel
|
module ActiveModel
|
||||||
class Serializer
|
class Serializer
|
||||||
@ -37,12 +38,12 @@ module ActiveModel
|
|||||||
# 2) as 'object.comments.last(1)' and named 'last_comments'.
|
# 2) as 'object.comments.last(1)' and named 'last_comments'.
|
||||||
#
|
#
|
||||||
# PostSerializer._reflections # =>
|
# PostSerializer._reflections # =>
|
||||||
# # [
|
# # {
|
||||||
# # HasOneReflection.new(:author, serializer: AuthorSerializer),
|
# # author: HasOneReflection.new(:author, serializer: AuthorSerializer),
|
||||||
# # HasManyReflection.new(:comments)
|
# # comments: HasManyReflection.new(:comments)
|
||||||
# # HasManyReflection.new(:comments, { key: :last_comments }, #<Block>)
|
# # last_comments: HasManyReflection.new(:comments, { key: :last_comments }, #<Block>)
|
||||||
# # HasManyReflection.new(:secret_meta_data, { if: :is_admin? })
|
# # secret_meta_data: HasManyReflection.new(:secret_meta_data, { if: :is_admin? })
|
||||||
# # ]
|
# # }
|
||||||
#
|
#
|
||||||
# So you can inspect reflections in your Adapters.
|
# So you can inspect reflections in your Adapters.
|
||||||
class Reflection < Field
|
class Reflection < Field
|
||||||
@ -70,8 +71,8 @@ module ActiveModel
|
|||||||
# meta ids: ids
|
# meta ids: ids
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
def link(name, value = nil, &block)
|
def link(name, value = nil)
|
||||||
options[:links][name] = block || value
|
options[:links][name] = block_given? ? Proc.new : value
|
||||||
:nil
|
:nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -85,8 +86,8 @@ module ActiveModel
|
|||||||
# href object.blog.id.to_s
|
# href object.blog.id.to_s
|
||||||
# meta(id: object.blog.id)
|
# meta(id: object.blog.id)
|
||||||
# end
|
# end
|
||||||
def meta(value = nil, &block)
|
def meta(value = nil)
|
||||||
options[:meta] = block || value
|
options[:meta] = block_given? ? Proc.new : value
|
||||||
:nil
|
:nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -118,6 +119,20 @@ module ActiveModel
|
|||||||
:nil
|
:nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def collection?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_data?(include_slice)
|
||||||
|
include_data_setting = options[:include_data_setting]
|
||||||
|
case include_data_setting
|
||||||
|
when :if_sideloaded then include_slice.key?(name)
|
||||||
|
when true then true
|
||||||
|
when false then false
|
||||||
|
else fail ArgumentError, "Unknown include_data_setting '#{include_data_setting.inspect}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# @param serializer [ActiveModel::Serializer]
|
# @param serializer [ActiveModel::Serializer]
|
||||||
# @yield [ActiveModel::Serializer]
|
# @yield [ActiveModel::Serializer]
|
||||||
# @return [:nil, associated resource or resource collection]
|
# @return [:nil, associated resource or resource collection]
|
||||||
@ -156,62 +171,18 @@ module ActiveModel
|
|||||||
#
|
#
|
||||||
# @api private
|
# @api private
|
||||||
def build_association(parent_serializer, parent_serializer_options, include_slice = {})
|
def build_association(parent_serializer, parent_serializer_options, include_slice = {})
|
||||||
reflection_options = options.dup
|
association_options = {
|
||||||
|
parent_serializer: parent_serializer,
|
||||||
# Pass the parent's namespace onto the child serializer
|
parent_serializer_options: parent_serializer_options,
|
||||||
reflection_options[:namespace] ||= parent_serializer_options[:namespace]
|
include_slice: include_slice
|
||||||
|
}
|
||||||
association_value = value(parent_serializer, include_slice)
|
Association.new(self, association_options)
|
||||||
serializer_class = parent_serializer.class.serializer_for(association_value, reflection_options)
|
|
||||||
reflection_options[:include_data] = include_data?(include_slice)
|
|
||||||
reflection_options[:links] = options[:links]
|
|
||||||
reflection_options[:meta] = options[:meta]
|
|
||||||
|
|
||||||
if serializer_class
|
|
||||||
serializer = catch(:no_serializer) do
|
|
||||||
serializer_class.new(
|
|
||||||
association_value,
|
|
||||||
serializer_options(parent_serializer, parent_serializer_options, reflection_options)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
if serializer.nil?
|
|
||||||
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
|
|
||||||
else
|
|
||||||
reflection_options[:serializer] = serializer
|
|
||||||
end
|
|
||||||
elsif !association_value.nil? && !association_value.instance_of?(Object)
|
|
||||||
reflection_options[:virtual_value] = association_value
|
|
||||||
end
|
|
||||||
|
|
||||||
block = nil
|
|
||||||
Association.new(name, reflection_options, block)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
# used in instance exec
|
# used in instance exec
|
||||||
attr_accessor :object, :scope
|
attr_accessor :object, :scope
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def include_data?(include_slice)
|
|
||||||
include_data_setting = options[:include_data_setting]
|
|
||||||
case include_data_setting
|
|
||||||
when :if_sideloaded then include_slice.key?(name)
|
|
||||||
when true then true
|
|
||||||
when false then false
|
|
||||||
else fail ArgumentError, "Unknown include_data_setting '#{include_data_setting.inspect}'"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
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] = parent_serializer.class
|
|
||||||
serializer_options
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
module ActiveModel
|
|
||||||
class Serializer
|
|
||||||
# @api private
|
|
||||||
class SingularReflection < Reflection
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -257,7 +257,8 @@ module ActiveModelSerializers
|
|||||||
|
|
||||||
def process_relationships(serializer, include_slice)
|
def process_relationships(serializer, include_slice)
|
||||||
serializer.associations(include_slice).each do |association|
|
serializer.associations(include_slice).each do |association|
|
||||||
process_relationship(association.serializer, include_slice[association.key])
|
# TODO(BF): Process relationship without evaluating lazy_association
|
||||||
|
process_relationship(association.lazy_association.serializer, include_slice[association.key])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -15,9 +15,7 @@ module ActiveModelSerializers
|
|||||||
def as_json
|
def as_json
|
||||||
hash = {}
|
hash = {}
|
||||||
|
|
||||||
if association.options[:include_data]
|
hash[:data] = data_for(association) if association.include_data?
|
||||||
hash[:data] = data_for(association)
|
|
||||||
end
|
|
||||||
|
|
||||||
links = links_for(association)
|
links = links_for(association)
|
||||||
hash[:links] = links if links.any?
|
hash[:links] = links if links.any?
|
||||||
@ -35,14 +33,38 @@ module ActiveModelSerializers
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# TODO(BF): Avoid db hit on belong_to_ releationship by using foreign_key on self
|
||||||
def data_for(association)
|
def data_for(association)
|
||||||
serializer = association.serializer
|
if association.collection?
|
||||||
if serializer.respond_to?(:each)
|
data_for_many(association)
|
||||||
serializer.map { |s| ResourceIdentifier.new(s, serializable_resource_options).as_json }
|
else
|
||||||
elsif (virtual_value = association.options[:virtual_value])
|
data_for_one(association)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def data_for_one(association)
|
||||||
|
# TODO(BF): Process relationship without evaluating lazy_association
|
||||||
|
serializer = association.lazy_association.serializer
|
||||||
|
if (virtual_value = association.virtual_value)
|
||||||
virtual_value
|
virtual_value
|
||||||
elsif serializer && serializer.object
|
elsif serializer && association.object
|
||||||
ResourceIdentifier.new(serializer, serializable_resource_options).as_json
|
ResourceIdentifier.new(serializer, serializable_resource_options).as_json
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def data_for_many(association)
|
||||||
|
# TODO(BF): Process relationship without evaluating lazy_association
|
||||||
|
collection_serializer = association.lazy_association.serializer
|
||||||
|
if collection_serializer.respond_to?(:each)
|
||||||
|
collection_serializer.map do |serializer|
|
||||||
|
ResourceIdentifier.new(serializer, serializable_resource_options).as_json
|
||||||
|
end
|
||||||
|
elsif (virtual_value = association.virtual_value)
|
||||||
|
virtual_value
|
||||||
|
else
|
||||||
|
[]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -30,18 +30,17 @@ module ActiveModel
|
|||||||
def test_has_many_and_has_one
|
def test_has_many_and_has_one
|
||||||
@author_serializer.associations.each do |association|
|
@author_serializer.associations.each do |association|
|
||||||
key = association.key
|
key = association.key
|
||||||
serializer = association.serializer
|
serializer = association.lazy_association.serializer
|
||||||
options = association.options
|
|
||||||
|
|
||||||
case key
|
case key
|
||||||
when :posts
|
when :posts
|
||||||
assert_equal true, options.fetch(:include_data)
|
assert_equal true, association.include_data?
|
||||||
assert_kind_of(ActiveModelSerializers.config.collection_serializer, serializer)
|
assert_kind_of(ActiveModelSerializers.config.collection_serializer, serializer)
|
||||||
when :bio
|
when :bio
|
||||||
assert_equal true, options.fetch(:include_data)
|
assert_equal true, association.include_data?
|
||||||
assert_nil serializer
|
assert_nil serializer
|
||||||
when :roles
|
when :roles
|
||||||
assert_equal true, options.fetch(:include_data)
|
assert_equal true, association.include_data?
|
||||||
assert_kind_of(ActiveModelSerializers.config.collection_serializer, serializer)
|
assert_kind_of(ActiveModelSerializers.config.collection_serializer, serializer)
|
||||||
else
|
else
|
||||||
flunk "Unknown association: #{key}"
|
flunk "Unknown association: #{key}"
|
||||||
@ -56,12 +55,11 @@ module ActiveModel
|
|||||||
end
|
end
|
||||||
post_serializer_class.new(@post).associations.each do |association|
|
post_serializer_class.new(@post).associations.each do |association|
|
||||||
key = association.key
|
key = association.key
|
||||||
serializer = association.serializer
|
serializer = association.lazy_association.serializer
|
||||||
options = association.options
|
|
||||||
|
|
||||||
assert_equal :tags, key
|
assert_equal :tags, key
|
||||||
assert_nil serializer
|
assert_nil serializer
|
||||||
assert_equal [{ id: 'tagid', name: '#hashtagged' }].to_json, options[:virtual_value].to_json
|
assert_equal [{ id: 'tagid', name: '#hashtagged' }].to_json, association.virtual_value.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -70,7 +68,7 @@ module ActiveModel
|
|||||||
.associations
|
.associations
|
||||||
.detect { |assoc| assoc.key == :comments }
|
.detect { |assoc| assoc.key == :comments }
|
||||||
|
|
||||||
comment_serializer = association.serializer.first
|
comment_serializer = association.lazy_association.serializer.first
|
||||||
class << comment_serializer
|
class << comment_serializer
|
||||||
def custom_options
|
def custom_options
|
||||||
instance_options
|
instance_options
|
||||||
@ -82,7 +80,7 @@ module ActiveModel
|
|||||||
def test_belongs_to
|
def test_belongs_to
|
||||||
@comment_serializer.associations.each do |association|
|
@comment_serializer.associations.each do |association|
|
||||||
key = association.key
|
key = association.key
|
||||||
serializer = association.serializer
|
serializer = association.lazy_association.serializer
|
||||||
|
|
||||||
case key
|
case key
|
||||||
when :post
|
when :post
|
||||||
@ -93,7 +91,7 @@ module ActiveModel
|
|||||||
flunk "Unknown association: #{key}"
|
flunk "Unknown association: #{key}"
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal true, association.options.fetch(:include_data)
|
assert_equal true, association.include_data?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -203,11 +201,11 @@ module ActiveModel
|
|||||||
@post_serializer.associations.each do |association|
|
@post_serializer.associations.each do |association|
|
||||||
case association.key
|
case association.key
|
||||||
when :comments
|
when :comments
|
||||||
assert_instance_of(ResourceNamespace::CommentSerializer, association.serializer.first)
|
assert_instance_of(ResourceNamespace::CommentSerializer, association.lazy_association.serializer.first)
|
||||||
when :author
|
when :author
|
||||||
assert_instance_of(ResourceNamespace::AuthorSerializer, association.serializer)
|
assert_instance_of(ResourceNamespace::AuthorSerializer, association.lazy_association.serializer)
|
||||||
when :description
|
when :description
|
||||||
assert_instance_of(ResourceNamespace::DescriptionSerializer, association.serializer)
|
assert_instance_of(ResourceNamespace::DescriptionSerializer, association.lazy_association.serializer)
|
||||||
else
|
else
|
||||||
flunk "Unknown association: #{key}"
|
flunk "Unknown association: #{key}"
|
||||||
end
|
end
|
||||||
@ -245,11 +243,11 @@ module ActiveModel
|
|||||||
@post_serializer.associations.each do |association|
|
@post_serializer.associations.each do |association|
|
||||||
case association.key
|
case association.key
|
||||||
when :comments
|
when :comments
|
||||||
assert_instance_of(PostSerializer::CommentSerializer, association.serializer.first)
|
assert_instance_of(PostSerializer::CommentSerializer, association.lazy_association.serializer.first)
|
||||||
when :author
|
when :author
|
||||||
assert_instance_of(PostSerializer::AuthorSerializer, association.serializer)
|
assert_instance_of(PostSerializer::AuthorSerializer, association.lazy_association.serializer)
|
||||||
when :description
|
when :description
|
||||||
assert_instance_of(PostSerializer::DescriptionSerializer, association.serializer)
|
assert_instance_of(PostSerializer::DescriptionSerializer, association.lazy_association.serializer)
|
||||||
else
|
else
|
||||||
flunk "Unknown association: #{key}"
|
flunk "Unknown association: #{key}"
|
||||||
end
|
end
|
||||||
@ -260,7 +258,7 @@ module ActiveModel
|
|||||||
def test_conditional_associations
|
def test_conditional_associations
|
||||||
model = Class.new(::Model) do
|
model = Class.new(::Model) do
|
||||||
attributes :true, :false
|
attributes :true, :false
|
||||||
associations :association
|
associations :something
|
||||||
end.new(true: true, false: false)
|
end.new(true: true, false: false)
|
||||||
|
|
||||||
scenarios = [
|
scenarios = [
|
||||||
@ -284,7 +282,7 @@ module ActiveModel
|
|||||||
|
|
||||||
scenarios.each do |s|
|
scenarios.each do |s|
|
||||||
serializer = Class.new(ActiveModel::Serializer) do
|
serializer = Class.new(ActiveModel::Serializer) do
|
||||||
belongs_to :association, s[:options]
|
belongs_to :something, s[:options]
|
||||||
|
|
||||||
def true
|
def true
|
||||||
true
|
true
|
||||||
@ -296,7 +294,7 @@ module ActiveModel
|
|||||||
end
|
end
|
||||||
|
|
||||||
hash = serializable(model, serializer: serializer).serializable_hash
|
hash = serializable(model, serializer: serializer).serializable_hash
|
||||||
assert_equal(s[:included], hash.key?(:association), "Error with #{s[:options]}")
|
assert_equal(s[:included], hash.key?(:something), "Error with #{s[:options]}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -341,8 +339,8 @@ module ActiveModel
|
|||||||
@author_serializer = AuthorSerializer.new(@author)
|
@author_serializer = AuthorSerializer.new(@author)
|
||||||
@inherited_post_serializer = InheritedPostSerializer.new(@post)
|
@inherited_post_serializer = InheritedPostSerializer.new(@post)
|
||||||
@inherited_author_serializer = InheritedAuthorSerializer.new(@author)
|
@inherited_author_serializer = InheritedAuthorSerializer.new(@author)
|
||||||
@author_associations = @author_serializer.associations.to_a
|
@author_associations = @author_serializer.associations.to_a.sort_by(&:name)
|
||||||
@inherited_author_associations = @inherited_author_serializer.associations.to_a
|
@inherited_author_associations = @inherited_author_serializer.associations.to_a.sort_by(&:name)
|
||||||
@post_associations = @post_serializer.associations.to_a
|
@post_associations = @post_serializer.associations.to_a
|
||||||
@inherited_post_associations = @inherited_post_serializer.associations.to_a
|
@inherited_post_associations = @inherited_post_serializer.associations.to_a
|
||||||
end
|
end
|
||||||
@ -361,28 +359,35 @@ module ActiveModel
|
|||||||
|
|
||||||
test 'a serializer inheriting from another serializer can redefine has_many and has_one associations' do
|
test 'a serializer inheriting from another serializer can redefine has_many and has_one associations' do
|
||||||
expected = [:roles, :bio].sort
|
expected = [:roles, :bio].sort
|
||||||
result = (@inherited_author_associations - @author_associations).map(&:name).sort
|
result = (@inherited_author_associations.map(&:reflection) - @author_associations.map(&:reflection)).map(&:name)
|
||||||
assert_equal(result, expected)
|
assert_equal(result, expected)
|
||||||
|
assert_equal [true, false, true], @inherited_author_associations.map(&:polymorphic?)
|
||||||
|
assert_equal [false, false, false], @author_associations.map(&:polymorphic?)
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'a serializer inheriting from another serializer can redefine belongs_to associations' do
|
test 'a serializer inheriting from another serializer can redefine belongs_to associations' do
|
||||||
assert_equal [:author, :comments, :blog], @post_associations.map(&:name)
|
assert_equal [:author, :comments, :blog], @post_associations.map(&:name)
|
||||||
assert_equal [:author, :comments, :blog, :comments], @inherited_post_associations.map(&:name)
|
assert_equal [:author, :comments, :blog, :comments], @inherited_post_associations.map(&:name)
|
||||||
|
|
||||||
refute @post_associations.detect { |assoc| assoc.name == :author }.options.key?(:polymorphic)
|
refute @post_associations.detect { |assoc| assoc.name == :author }.polymorphic?
|
||||||
assert_equal true, @inherited_post_associations.detect { |assoc| assoc.name == :author }.options.fetch(:polymorphic)
|
assert @inherited_post_associations.detect { |assoc| assoc.name == :author }.polymorphic?
|
||||||
|
|
||||||
refute @post_associations.detect { |assoc| assoc.name == :comments }.options.key?(:key)
|
refute @post_associations.detect { |assoc| assoc.name == :comments }.key?
|
||||||
original_comment_assoc, new_comments_assoc = @inherited_post_associations.select { |assoc| assoc.name == :comments }
|
original_comment_assoc, new_comments_assoc = @inherited_post_associations.select { |assoc| assoc.name == :comments }
|
||||||
refute original_comment_assoc.options.key?(:key)
|
refute original_comment_assoc.key?
|
||||||
assert_equal :reviews, new_comments_assoc.options.fetch(:key)
|
assert_equal :reviews, new_comments_assoc.key
|
||||||
|
|
||||||
assert_equal @post_associations.detect { |assoc| assoc.name == :blog }, @inherited_post_associations.detect { |assoc| assoc.name == :blog }
|
original_blog = @post_associations.detect { |assoc| assoc.name == :blog }
|
||||||
|
inherited_blog = @inherited_post_associations.detect { |assoc| assoc.name == :blog }
|
||||||
|
original_parent_serializer = original_blog.lazy_association.association_options.delete(:parent_serializer)
|
||||||
|
inherited_parent_serializer = inherited_blog.lazy_association.association_options.delete(:parent_serializer)
|
||||||
|
assert_equal PostSerializer, original_parent_serializer.class
|
||||||
|
assert_equal InheritedPostSerializer, inherited_parent_serializer.class
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'a serializer inheriting from another serializer can have an additional association with the same name but with different key' do
|
test 'a serializer inheriting from another serializer can have an additional association with the same name but with different key' do
|
||||||
expected = [:author, :comments, :blog, :reviews].sort
|
expected = [:author, :comments, :blog, :reviews].sort
|
||||||
result = @inherited_post_serializer.associations.map { |a| a.options.fetch(:key, a.name) }.sort
|
result = @inherited_post_serializer.associations.map(&:key).sort
|
||||||
assert_equal(result, expected)
|
assert_equal(result, expected)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -25,6 +25,10 @@ module ActiveModel
|
|||||||
@instance_options = {}
|
@instance_options = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def evaluate_association_value(association)
|
||||||
|
association.lazy_association.eval_reflection_block
|
||||||
|
end
|
||||||
|
|
||||||
# TODO: Remaining tests
|
# TODO: Remaining tests
|
||||||
# test_reflection_value_block_with_scope
|
# test_reflection_value_block_with_scope
|
||||||
# test_reflection_value_uses_serializer_instance_method
|
# test_reflection_value_uses_serializer_instance_method
|
||||||
@ -57,7 +61,7 @@ module ActiveModel
|
|||||||
assert_equal true, reflection.options.fetch(:include_data_setting)
|
assert_equal true, reflection.options.fetch(:include_data_setting)
|
||||||
|
|
||||||
include_slice = :does_not_matter
|
include_slice = :does_not_matter
|
||||||
assert_equal @model.blog, reflection.value(serializer_instance, include_slice)
|
assert_equal @model.blog, reflection.send(:value, serializer_instance, include_slice)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_reflection_value_block
|
def test_reflection_value_block
|
||||||
@ -77,7 +81,7 @@ module ActiveModel
|
|||||||
assert_equal true, reflection.options.fetch(:include_data_setting)
|
assert_equal true, reflection.options.fetch(:include_data_setting)
|
||||||
|
|
||||||
include_slice = :does_not_matter
|
include_slice = :does_not_matter
|
||||||
assert_equal @model.blog, reflection.value(serializer_instance, include_slice)
|
assert_equal @model.blog, reflection.send(:value, serializer_instance, include_slice)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_reflection_value_block_with_explicit_include_data_true
|
def test_reflection_value_block_with_explicit_include_data_true
|
||||||
@ -98,7 +102,7 @@ module ActiveModel
|
|||||||
assert_equal true, reflection.options.fetch(:include_data_setting)
|
assert_equal true, reflection.options.fetch(:include_data_setting)
|
||||||
|
|
||||||
include_slice = :does_not_matter
|
include_slice = :does_not_matter
|
||||||
assert_equal @model.blog, reflection.value(serializer_instance, include_slice)
|
assert_equal @model.blog, reflection.send(:value, serializer_instance, include_slice)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_reflection_value_block_with_include_data_false_mutates_the_reflection_include_data
|
def test_reflection_value_block_with_include_data_false_mutates_the_reflection_include_data
|
||||||
@ -117,7 +121,7 @@ module ActiveModel
|
|||||||
assert_respond_to reflection.block, :call
|
assert_respond_to reflection.block, :call
|
||||||
assert_equal true, reflection.options.fetch(:include_data_setting)
|
assert_equal true, reflection.options.fetch(:include_data_setting)
|
||||||
include_slice = :does_not_matter
|
include_slice = :does_not_matter
|
||||||
assert_nil reflection.value(serializer_instance, include_slice)
|
assert_nil reflection.send(:value, serializer_instance, include_slice)
|
||||||
assert_equal false, reflection.options.fetch(:include_data_setting)
|
assert_equal false, reflection.options.fetch(:include_data_setting)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -137,7 +141,7 @@ module ActiveModel
|
|||||||
assert_respond_to reflection.block, :call
|
assert_respond_to reflection.block, :call
|
||||||
assert_equal true, reflection.options.fetch(:include_data_setting)
|
assert_equal true, reflection.options.fetch(:include_data_setting)
|
||||||
include_slice = {}
|
include_slice = {}
|
||||||
assert_nil reflection.value(serializer_instance, include_slice)
|
assert_nil reflection.send(:value, serializer_instance, include_slice)
|
||||||
assert_equal :if_sideloaded, reflection.options.fetch(:include_data_setting)
|
assert_equal :if_sideloaded, reflection.options.fetch(:include_data_setting)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -157,7 +161,7 @@ module ActiveModel
|
|||||||
assert_respond_to reflection.block, :call
|
assert_respond_to reflection.block, :call
|
||||||
assert_equal true, reflection.options.fetch(:include_data_setting)
|
assert_equal true, reflection.options.fetch(:include_data_setting)
|
||||||
include_slice = { blog: :does_not_matter }
|
include_slice = { blog: :does_not_matter }
|
||||||
assert_equal @model.blog, reflection.value(serializer_instance, include_slice)
|
assert_equal @model.blog, reflection.send(:value, serializer_instance, include_slice)
|
||||||
assert_equal :if_sideloaded, reflection.options.fetch(:include_data_setting)
|
assert_equal :if_sideloaded, reflection.options.fetch(:include_data_setting)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -175,6 +179,13 @@ module ActiveModel
|
|||||||
|
|
||||||
# Build Association
|
# Build Association
|
||||||
association = reflection.build_association(serializer_instance, @instance_options)
|
association = reflection.build_association(serializer_instance, @instance_options)
|
||||||
|
|
||||||
|
# Assert association links empty when not yet evaluated
|
||||||
|
assert_equal @empty_links, reflection.options.fetch(:links)
|
||||||
|
assert_equal @empty_links, association.links
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
assert_equal @expected_links, association.links
|
assert_equal @expected_links, association.links
|
||||||
assert_equal @expected_links, reflection.options.fetch(:links)
|
assert_equal @expected_links, reflection.options.fetch(:links)
|
||||||
end
|
end
|
||||||
@ -195,9 +206,16 @@ module ActiveModel
|
|||||||
|
|
||||||
# Build Association
|
# Build Association
|
||||||
association = reflection.build_association(serializer_instance, @instance_options)
|
association = reflection.build_association(serializer_instance, @instance_options)
|
||||||
|
|
||||||
|
# Assert association links empty when not yet evaluated
|
||||||
|
assert_equal @empty_links, association.links
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
# Assert before instance_eval link
|
# Assert before instance_eval link
|
||||||
link = association.links.fetch(:self)
|
link = association.links.fetch(:self)
|
||||||
assert_respond_to link, :call
|
assert_respond_to link, :call
|
||||||
|
assert_respond_to reflection.options.fetch(:links).fetch(:self), :call
|
||||||
|
|
||||||
# Assert after instance_eval link
|
# Assert after instance_eval link
|
||||||
assert_equal @expected_links.fetch(:self), reflection.instance_eval(&link)
|
assert_equal @expected_links.fetch(:self), reflection.instance_eval(&link)
|
||||||
@ -218,6 +236,9 @@ module ActiveModel
|
|||||||
|
|
||||||
# Build Association
|
# Build Association
|
||||||
association = reflection.build_association(serializer_instance, @instance_options)
|
association = reflection.build_association(serializer_instance, @instance_options)
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
assert_equal @expected_meta, association.meta
|
assert_equal @expected_meta, association.meta
|
||||||
assert_equal @expected_meta, reflection.options.fetch(:meta)
|
assert_equal @expected_meta, reflection.options.fetch(:meta)
|
||||||
end
|
end
|
||||||
@ -239,6 +260,9 @@ module ActiveModel
|
|||||||
# Build Association
|
# Build Association
|
||||||
association = reflection.build_association(serializer_instance, @instance_options)
|
association = reflection.build_association(serializer_instance, @instance_options)
|
||||||
# Assert before instance_eval meta
|
# Assert before instance_eval meta
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
assert_respond_to association.meta, :call
|
assert_respond_to association.meta, :call
|
||||||
assert_respond_to reflection.options.fetch(:meta), :call
|
assert_respond_to reflection.options.fetch(:meta), :call
|
||||||
|
|
||||||
@ -271,6 +295,8 @@ module ActiveModel
|
|||||||
assert_nil association.meta
|
assert_nil association.meta
|
||||||
assert_nil reflection.options.fetch(:meta)
|
assert_nil reflection.options.fetch(:meta)
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
link = association.links.fetch(:self)
|
link = association.links.fetch(:self)
|
||||||
assert_respond_to link, :call
|
assert_respond_to link, :call
|
||||||
assert_respond_to reflection.options.fetch(:links).fetch(:self), :call
|
assert_respond_to reflection.options.fetch(:links).fetch(:self), :call
|
||||||
@ -279,7 +305,7 @@ module ActiveModel
|
|||||||
# Assert after instance_eval link
|
# Assert after instance_eval link
|
||||||
assert_equal 'no_uri_validation', reflection.instance_eval(&link)
|
assert_equal 'no_uri_validation', reflection.instance_eval(&link)
|
||||||
assert_equal @expected_meta, reflection.options.fetch(:meta)
|
assert_equal @expected_meta, reflection.options.fetch(:meta)
|
||||||
assert_nil association.meta
|
assert_equal @expected_meta, association.meta
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/AbcSize
|
# rubocop:enable Metrics/AbcSize
|
||||||
|
|
||||||
@ -307,6 +333,9 @@ module ActiveModel
|
|||||||
assert_nil reflection.options.fetch(:meta)
|
assert_nil reflection.options.fetch(:meta)
|
||||||
|
|
||||||
# Assert before instance_eval link
|
# Assert before instance_eval link
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
link = association.links.fetch(:self)
|
link = association.links.fetch(:self)
|
||||||
assert_nil reflection.options.fetch(:meta)
|
assert_nil reflection.options.fetch(:meta)
|
||||||
assert_respond_to link, :call
|
assert_respond_to link, :call
|
||||||
@ -317,11 +346,11 @@ module ActiveModel
|
|||||||
assert_respond_to association.links.fetch(:self), :call
|
assert_respond_to association.links.fetch(:self), :call
|
||||||
# Assert before instance_eval link meta
|
# Assert before instance_eval link meta
|
||||||
assert_respond_to reflection.options.fetch(:meta), :call
|
assert_respond_to reflection.options.fetch(:meta), :call
|
||||||
assert_nil association.meta
|
assert_respond_to association.meta, :call
|
||||||
|
|
||||||
# Assert after instance_eval link meta
|
# Assert after instance_eval link meta
|
||||||
assert_equal @expected_meta, reflection.instance_eval(&reflection.options.fetch(:meta))
|
assert_equal @expected_meta, reflection.instance_eval(&reflection.options.fetch(:meta))
|
||||||
assert_nil association.meta
|
assert_respond_to association.meta, :call
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/AbcSize
|
# rubocop:enable Metrics/AbcSize
|
||||||
|
|
||||||
@ -342,6 +371,9 @@ module ActiveModel
|
|||||||
# Build Association
|
# Build Association
|
||||||
association = reflection.build_association(serializer_instance, @instance_options)
|
association = reflection.build_association(serializer_instance, @instance_options)
|
||||||
# Assert before instance_eval link
|
# Assert before instance_eval link
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
link = association.links.fetch(:self)
|
link = association.links.fetch(:self)
|
||||||
assert_respond_to link, :call
|
assert_respond_to link, :call
|
||||||
|
|
||||||
@ -365,6 +397,9 @@ module ActiveModel
|
|||||||
reflection = serializer_class._reflections.fetch(:blog)
|
reflection = serializer_class._reflections.fetch(:blog)
|
||||||
assert_nil reflection.options.fetch(:meta)
|
assert_nil reflection.options.fetch(:meta)
|
||||||
association = reflection.build_association(serializer_instance, @instance_options)
|
association = reflection.build_association(serializer_instance, @instance_options)
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
assert_equal model1_meta, association.meta
|
assert_equal model1_meta, association.meta
|
||||||
assert_equal model1_meta, reflection.options.fetch(:meta)
|
assert_equal model1_meta, reflection.options.fetch(:meta)
|
||||||
|
|
||||||
@ -380,6 +415,9 @@ module ActiveModel
|
|||||||
assert_equal model1_meta, reflection.options.fetch(:meta)
|
assert_equal model1_meta, reflection.options.fetch(:meta)
|
||||||
|
|
||||||
association = reflection.build_association(serializer_instance, @instance_options)
|
association = reflection.build_association(serializer_instance, @instance_options)
|
||||||
|
|
||||||
|
evaluate_association_value(association)
|
||||||
|
|
||||||
assert_equal model2_meta, association.meta
|
assert_equal model2_meta, association.meta
|
||||||
assert_equal model2_meta, reflection.options.fetch(:meta)
|
assert_equal model2_meta, reflection.options.fetch(:meta)
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user