mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-22 22:06:50 +00:00
Associations refactoring
* Move all associations related code from Serializer class to Associations module * Introduce Reflection class hierarchy * Introduce Association class * Rid off Serializer#each_association * Introduce Serializer#associations enumerator
This commit is contained in:
parent
438d8f411a
commit
2952a332e0
@ -3,16 +3,18 @@ require 'thread_safe'
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
extend ActiveSupport::Autoload
|
||||
|
||||
autoload :Configuration
|
||||
autoload :ArraySerializer
|
||||
autoload :Adapter
|
||||
autoload :Lint
|
||||
autoload :Associations
|
||||
include Configuration
|
||||
include Associations
|
||||
|
||||
class << self
|
||||
attr_accessor :_attributes
|
||||
attr_accessor :_attributes_keys
|
||||
attr_accessor :_associations
|
||||
attr_accessor :_urls
|
||||
attr_accessor :_cache
|
||||
attr_accessor :_fragmented
|
||||
@ -26,10 +28,10 @@ module ActiveModel
|
||||
def self.inherited(base)
|
||||
base._attributes = self._attributes.try(:dup) || []
|
||||
base._attributes_keys = self._attributes_keys.try(:dup) || {}
|
||||
base._associations = self._associations.try(:dup) || {}
|
||||
base._urls = []
|
||||
serializer_file = File.open(caller.first[/^[^:]+/])
|
||||
base._cache_digest = Digest::MD5.hexdigest(serializer_file.read)
|
||||
super
|
||||
end
|
||||
|
||||
def self.attributes(*attrs)
|
||||
@ -46,7 +48,7 @@ module ActiveModel
|
||||
|
||||
def self.attribute(attr, options = {})
|
||||
key = options.fetch(:key, attr)
|
||||
@_attributes_keys[attr] = {key: key} if key != attr
|
||||
@_attributes_keys[attr] = { key: key } if key != attr
|
||||
@_attributes << key unless @_attributes.include?(key)
|
||||
define_method key do
|
||||
object.read_attribute_for_serialization(attr)
|
||||
@ -66,51 +68,6 @@ module ActiveModel
|
||||
@_cache_options = (options.empty?) ? nil : options
|
||||
end
|
||||
|
||||
# Defines an association in the object should be rendered.
|
||||
#
|
||||
# The serializer object should implement the association name
|
||||
# as a method which should return an array when invoked. If a method
|
||||
# with the association name does not exist, the association name is
|
||||
# dispatched to the serialized object.
|
||||
def self.has_many(*attrs)
|
||||
associate(:has_many, attrs)
|
||||
end
|
||||
|
||||
# Defines an association in the object that should be rendered.
|
||||
#
|
||||
# The serializer object should implement the association name
|
||||
# as a method which should return an object when invoked. If a method
|
||||
# with the association name does not exist, the association name is
|
||||
# dispatched to the serialized object.
|
||||
def self.belongs_to(*attrs)
|
||||
associate(:belongs_to, attrs)
|
||||
end
|
||||
|
||||
# Defines an association in the object should be rendered.
|
||||
#
|
||||
# The serializer object should implement the association name
|
||||
# as a method which should return an object when invoked. If a method
|
||||
# with the association name does not exist, the association name is
|
||||
# dispatched to the serialized object.
|
||||
def self.has_one(*attrs)
|
||||
associate(:has_one, attrs)
|
||||
end
|
||||
|
||||
def self.associate(type, attrs) #:nodoc:
|
||||
options = attrs.extract_options!
|
||||
self._associations = _associations.dup
|
||||
|
||||
attrs.each do |attr|
|
||||
unless method_defined?(attr)
|
||||
define_method attr do
|
||||
object.send attr
|
||||
end
|
||||
end
|
||||
|
||||
self._associations[attr] = {type: type, association_options: options}
|
||||
end
|
||||
end
|
||||
|
||||
def self.url(attr)
|
||||
@_urls.push attr
|
||||
end
|
||||
@ -125,9 +82,7 @@ module ActiveModel
|
||||
elsif resource.respond_to?(:to_ary)
|
||||
config.array_serializer
|
||||
else
|
||||
options
|
||||
.fetch(:association_options, {})
|
||||
.fetch(:serializer, get_serializer_for(resource.class))
|
||||
options.fetch(:serializer, get_serializer_for(resource.class))
|
||||
end
|
||||
end
|
||||
|
||||
@ -199,48 +154,10 @@ module ActiveModel
|
||||
end
|
||||
end
|
||||
|
||||
def each_association(&block)
|
||||
self.class._associations.dup.each do |name, association_options|
|
||||
next unless object
|
||||
association_value = send(name)
|
||||
|
||||
serializer_class = ActiveModel::Serializer.serializer_for(association_value, association_options)
|
||||
|
||||
if serializer_class
|
||||
begin
|
||||
serializer = serializer_class.new(
|
||||
association_value,
|
||||
options.except(:serializer).merge(serializer_from_options(association_options))
|
||||
)
|
||||
rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
|
||||
virtual_value = association_value
|
||||
virtual_value = virtual_value.as_json if virtual_value.respond_to?(:as_json)
|
||||
association_options[:association_options][:virtual_value] = virtual_value
|
||||
end
|
||||
elsif !association_value.nil? && !association_value.instance_of?(Object)
|
||||
association_options[:association_options][:virtual_value] = association_value
|
||||
end
|
||||
|
||||
association_key = association_options[:association_options][:key] || name
|
||||
if block_given?
|
||||
block.call(association_key, serializer, association_options[:association_options])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def serializer_from_options(options)
|
||||
opts = {}
|
||||
serializer = options.fetch(:association_options, {}).fetch(:serializer, nil)
|
||||
opts[:serializer] = serializer if serializer
|
||||
opts
|
||||
end
|
||||
|
||||
def self.serializers_cache
|
||||
@serializers_cache ||= ThreadSafe::Cache.new
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :options
|
||||
|
||||
def self.get_serializer_for(klass)
|
||||
@ -255,6 +172,5 @@ module ActiveModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -7,7 +7,7 @@ module ActiveModel
|
||||
def serializable_hash(options = nil)
|
||||
options ||= {}
|
||||
if serializer.respond_to?(:each)
|
||||
@result = serializer.map{|s| FlattenJson.new(s).serializable_hash(options) }
|
||||
@result = serializer.map { |s| FlattenJson.new(s).serializable_hash(options) }
|
||||
else
|
||||
@hash = {}
|
||||
|
||||
@ -15,23 +15,25 @@ module ActiveModel
|
||||
serializer.attributes(options)
|
||||
end
|
||||
|
||||
serializer.each_association do |key, association, opts|
|
||||
if association.respond_to?(:each)
|
||||
array_serializer = association
|
||||
@hash[key] = array_serializer.map do |item|
|
||||
serializer.associations.each do |association|
|
||||
serializer = association.serializer
|
||||
opts = 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)
|
||||
end
|
||||
end
|
||||
else
|
||||
if association && association.object
|
||||
@hash[key] = cache_check(association) do
|
||||
association.attributes(options)
|
||||
@hash[association.key] =
|
||||
if serializer && serializer.object
|
||||
cache_check(serializer) do
|
||||
serializer.attributes(options)
|
||||
end
|
||||
elsif opts[:virtual_value]
|
||||
@hash[key] = opts[:virtual_value]
|
||||
else
|
||||
@hash[key] = nil
|
||||
opts[:virtual_value]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -75,8 +75,10 @@ module ActiveModel
|
||||
end
|
||||
|
||||
serializers.each do |serializer|
|
||||
serializer.each_association do |key, association, opts|
|
||||
add_included(key, association, resource_path) if association
|
||||
serializer.associations.each do |association|
|
||||
serializer = association.serializer
|
||||
|
||||
add_included(association.key, serializer, resource_path) if serializer
|
||||
end if include_nested_assoc? resource_path
|
||||
end
|
||||
end
|
||||
@ -131,22 +133,26 @@ module ActiveModel
|
||||
def add_resource_relationships(attrs, serializer, options = {})
|
||||
options[:add_included] = options.fetch(:add_included, true)
|
||||
|
||||
serializer.each_association do |key, association, opts|
|
||||
serializer.associations.each do |association|
|
||||
key = association.key
|
||||
serializer = association.serializer
|
||||
opts = association.options
|
||||
|
||||
attrs[:relationships] ||= {}
|
||||
|
||||
if association.respond_to?(:each)
|
||||
add_relationships(attrs, key, association)
|
||||
if serializer.respond_to?(:each)
|
||||
add_relationships(attrs, key, serializer)
|
||||
else
|
||||
if opts[:virtual_value]
|
||||
add_relationship(attrs, key, nil, opts[:virtual_value])
|
||||
else
|
||||
add_relationship(attrs, key, association)
|
||||
add_relationship(attrs, key, serializer)
|
||||
end
|
||||
end
|
||||
|
||||
if options[:add_included]
|
||||
Array(association).each do |association|
|
||||
add_included(key, association)
|
||||
Array(serializer).each do |serializer|
|
||||
add_included(key, serializer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
21
lib/active_model/serializer/association.rb
Normal file
21
lib/active_model/serializer/association.rb
Normal file
@ -0,0 +1,21 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# This class hold all information about serializer's association.
|
||||
#
|
||||
# @param [Symbol] name
|
||||
# @param [ActiveModel::Serializer] serializer
|
||||
# @param [Hash{Symbol => Object}] options
|
||||
#
|
||||
# @example
|
||||
# Association.new(:comments, CommentSummarySerializer, embed: :ids)
|
||||
#
|
||||
Association = Struct.new(:name, :serializer, :options) do
|
||||
|
||||
# @return [Symbol]
|
||||
#
|
||||
def key
|
||||
options.fetch(:key, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
107
lib/active_model/serializer/associations.rb
Normal file
107
lib/active_model/serializer/associations.rb
Normal file
@ -0,0 +1,107 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# Defines an association in the object should be rendered.
|
||||
#
|
||||
# The serializer object should implement the association name
|
||||
# as a method which should return an array when invoked. If a method
|
||||
# with the association name does not exist, the association name is
|
||||
# dispatched to the serialized object.
|
||||
#
|
||||
module Associations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do |base|
|
||||
class << base
|
||||
attr_accessor :_reflections
|
||||
end
|
||||
|
||||
autoload :Association
|
||||
autoload :Reflection
|
||||
autoload :SingularReflection
|
||||
autoload :CollectionReflection
|
||||
autoload :BelongsToReflection
|
||||
autoload :HasOneReflection
|
||||
autoload :HasManyReflection
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def inherited(base)
|
||||
base._reflections = self._reflections.try(:dup) || []
|
||||
end
|
||||
|
||||
# @param [Array(Array<Symbol>, Hash{Symbol => Object})] attrs
|
||||
# @return [void]
|
||||
#
|
||||
# @example
|
||||
# has_many :comments, serializer: CommentSummarySerializer
|
||||
# has_many :commits, authors
|
||||
#
|
||||
def has_many(*attrs)
|
||||
associate attrs do |name, options|
|
||||
HasManyReflection.new(name, options)
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Array(Array<Symbol>, Hash{Symbol => Object})] attrs
|
||||
# @return [void]
|
||||
#
|
||||
# @example
|
||||
# belongs_to :author, serializer: AuthorSerializer
|
||||
#
|
||||
def belongs_to(*attrs)
|
||||
associate attrs do |name, options|
|
||||
BelongsToReflection.new(name, options)
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Array(Array<Symbol>, Hash{Symbol => Object})] attrs
|
||||
# @return [void]
|
||||
#
|
||||
# @example
|
||||
# has_one :author, serializer: AuthorSerializer
|
||||
#
|
||||
def has_one(*attrs)
|
||||
associate attrs do |name, options|
|
||||
HasOneReflection.new(name, options)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Add reflection and define {name} accessor.
|
||||
# @param [Array<Symbol>]
|
||||
# @yield [Symbol] return reflection
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def associate(attrs)
|
||||
options = attrs.extract_options!
|
||||
|
||||
self._reflections = _reflections.dup
|
||||
|
||||
attrs.each do |name|
|
||||
unless method_defined?(name)
|
||||
define_method name do
|
||||
object.send name
|
||||
end
|
||||
end
|
||||
|
||||
self._reflections << yield(name, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Enumerator<Association>]
|
||||
#
|
||||
def associations
|
||||
return unless object
|
||||
|
||||
Enumerator.new do |y|
|
||||
self.class._reflections.each do |reflection|
|
||||
y.yield reflection.build_association(self, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
10
lib/active_model/serializer/belongs_to_reflection.rb
Normal file
10
lib/active_model/serializer/belongs_to_reflection.rb
Normal file
@ -0,0 +1,10 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# @api private
|
||||
class BelongsToReflection < SingularReflection
|
||||
def macro
|
||||
:belongs_to
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
7
lib/active_model/serializer/collection_reflection.rb
Normal file
7
lib/active_model/serializer/collection_reflection.rb
Normal file
@ -0,0 +1,7 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# @api private
|
||||
class CollectionReflection < Reflection
|
||||
end
|
||||
end
|
||||
end
|
||||
10
lib/active_model/serializer/has_many_reflection.rb
Normal file
10
lib/active_model/serializer/has_many_reflection.rb
Normal file
@ -0,0 +1,10 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# @api private
|
||||
class HasManyReflection < CollectionReflection
|
||||
def macro
|
||||
:has_many
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
10
lib/active_model/serializer/has_one_reflection.rb
Normal file
10
lib/active_model/serializer/has_one_reflection.rb
Normal file
@ -0,0 +1,10 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# @api private
|
||||
class HasOneReflection < SingularReflection
|
||||
def macro
|
||||
:has_one
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
74
lib/active_model/serializer/reflection.rb
Normal file
74
lib/active_model/serializer/reflection.rb
Normal file
@ -0,0 +1,74 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# Holds all the meta-data about an association as it was specified in the
|
||||
# ActiveModel::Serializer class.
|
||||
#
|
||||
# @example
|
||||
# class PostSerializer < ActiveModel::Serializer
|
||||
# has_one :author, serializer: AuthorSerializer
|
||||
# has_many :comments
|
||||
# end
|
||||
#
|
||||
# PostSerializer._reflections #=>
|
||||
# # [
|
||||
# # HasOneReflection.new(:author, serializer: AuthorSerializer),
|
||||
# # HasManyReflection.new(:comments)
|
||||
# # ]
|
||||
#
|
||||
# So you can inspect reflections in your Adapters.
|
||||
#
|
||||
Reflection = Struct.new(:name, :options) do
|
||||
# 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 [Hash{Symbol => Object}] parent_serializer_options
|
||||
#
|
||||
# @example
|
||||
# # Given the following serializer defined:
|
||||
# class PostSerializer < ActiveModel::Serializer
|
||||
# has_many :comments, serializer: CommentSummarySerializer
|
||||
# end
|
||||
#
|
||||
# # Then you instantiate your serializer
|
||||
# post_serializer = PostSerializer.new(post, foo: 'bar') #
|
||||
# # to build association for comments you need to get reflection
|
||||
# comments_reflection = PostSerializer._reflections.detect { |r| r.name == :comments }
|
||||
# # and #build_association
|
||||
# comments_reflection.build_association(post_serializer, foo: 'bar')
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def build_association(subject, parent_serializer_options)
|
||||
association_value = subject.send(name)
|
||||
reflection_options = options.dup
|
||||
serializer_class = ActiveModel::Serializer.serializer_for(association_value, reflection_options)
|
||||
|
||||
if serializer_class
|
||||
begin
|
||||
serializer = serializer_class.new(
|
||||
association_value,
|
||||
serializer_options(parent_serializer_options, reflection_options)
|
||||
)
|
||||
rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
|
||||
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
|
||||
end
|
||||
elsif !association_value.nil? && !association_value.instance_of?(Object)
|
||||
reflection_options[:virtual_value] = association_value
|
||||
end
|
||||
|
||||
Association.new(name, serializer, reflection_options)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serializer_options(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
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
7
lib/active_model/serializer/singular_reflection.rb
Normal file
7
lib/active_model/serializer/singular_reflection.rb
Normal file
@ -0,0 +1,7 @@
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# @api private
|
||||
class SingularReflection < Reflection
|
||||
end
|
||||
end
|
||||
end
|
||||
36
test/serializers/association_macros_test.rb
Normal file
36
test/serializers/association_macros_test.rb
Normal file
@ -0,0 +1,36 @@
|
||||
require 'test_helper'
|
||||
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
class AssociationMacrosTest < Minitest::Test
|
||||
AuthorSummarySerializer = Class.new
|
||||
class AssociationsTestSerializer < Serializer
|
||||
belongs_to :author, serializer: AuthorSummarySerializer
|
||||
has_many :comments, embed: :ids
|
||||
has_one :category
|
||||
end
|
||||
|
||||
def before_setup
|
||||
@reflections = AssociationsTestSerializer._reflections
|
||||
end
|
||||
|
||||
def test_has_one_defines_reflection
|
||||
has_one_reflection = HasOneReflection.new(:category, {})
|
||||
|
||||
assert_includes(@reflections, has_one_reflection)
|
||||
end
|
||||
|
||||
def test_has_many_defines_reflection
|
||||
has_many_reflection = HasManyReflection.new(:comments, embed: :ids)
|
||||
|
||||
assert_includes(@reflections, has_many_reflection)
|
||||
end
|
||||
|
||||
def test_belongs_to_defines_reflection
|
||||
belongs_to_reflection = BelongsToReflection.new(:author, serializer: AuthorSummarySerializer)
|
||||
|
||||
assert_includes(@reflections, belongs_to_reflection)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -45,21 +45,20 @@ module ActiveModel
|
||||
end
|
||||
|
||||
def test_has_many_and_has_one
|
||||
assert_equal(
|
||||
{ posts: { type: :has_many, association_options: { embed: :ids } },
|
||||
roles: { type: :has_many, association_options: { embed: :ids } },
|
||||
bio: { type: :has_one, association_options: {} } },
|
||||
@author_serializer.class._associations
|
||||
)
|
||||
@author_serializer.each_association do |key, serializer, options|
|
||||
if key == :posts
|
||||
assert_equal({embed: :ids}, options)
|
||||
@author_serializer.associations.each do |association|
|
||||
key = association.key
|
||||
serializer = association.serializer
|
||||
options = association.options
|
||||
|
||||
case key
|
||||
when :posts
|
||||
assert_equal({ embed: :ids }, options)
|
||||
assert_kind_of(ActiveModel::Serializer.config.array_serializer, serializer)
|
||||
elsif key == :bio
|
||||
when :bio
|
||||
assert_equal({}, options)
|
||||
assert_nil serializer
|
||||
elsif key == :roles
|
||||
assert_equal({embed: :ids}, options)
|
||||
when :roles
|
||||
assert_equal({ embed: :ids }, options)
|
||||
assert_kind_of(ActiveModel::Serializer.config.array_serializer, serializer)
|
||||
else
|
||||
flunk "Unknown association: #{key}"
|
||||
@ -68,7 +67,11 @@ module ActiveModel
|
||||
end
|
||||
|
||||
def test_has_many_with_no_serializer
|
||||
PostWithTagsSerializer.new(@post).each_association do |key, serializer, options|
|
||||
PostWithTagsSerializer.new(@post).associations.each do |association|
|
||||
key = association.key
|
||||
serializer = association.serializer
|
||||
options = association.options
|
||||
|
||||
assert_equal key, :tags
|
||||
assert_equal serializer, nil
|
||||
assert_equal [{ attributes: { name: "#hashtagged" }}].to_json, options[:virtual_value].to_json
|
||||
@ -76,70 +79,67 @@ module ActiveModel
|
||||
end
|
||||
|
||||
def test_serializer_options_are_passed_into_associations_serializers
|
||||
@post_serializer.each_association do |key, association|
|
||||
if key == :comments
|
||||
assert association.first.custom_options[:custom_options]
|
||||
end
|
||||
end
|
||||
association = @post_serializer
|
||||
.associations
|
||||
.detect { |association| association.key == :comments }
|
||||
|
||||
assert association.serializer.first.custom_options[:custom_options]
|
||||
end
|
||||
|
||||
def test_belongs_to
|
||||
assert_equal(
|
||||
{ post: { type: :belongs_to, association_options: {} },
|
||||
author: { type: :belongs_to, association_options: {} } },
|
||||
@comment_serializer.class._associations
|
||||
)
|
||||
@comment_serializer.each_association do |key, serializer, options|
|
||||
if key == :post
|
||||
assert_equal({}, options)
|
||||
@comment_serializer.associations.each do |association|
|
||||
key = association.key
|
||||
serializer = association.serializer
|
||||
|
||||
case key
|
||||
when :post
|
||||
assert_kind_of(PostSerializer, serializer)
|
||||
elsif key == :author
|
||||
assert_equal({}, options)
|
||||
when :author
|
||||
assert_nil serializer
|
||||
else
|
||||
flunk "Unknown association: #{key}"
|
||||
end
|
||||
|
||||
assert_equal({}, association.options)
|
||||
end
|
||||
end
|
||||
|
||||
def test_belongs_to_with_custom_method
|
||||
blog_is_present = false
|
||||
|
||||
@post_serializer.each_association do |key, serializer, options|
|
||||
blog_is_present = true if key == :blog
|
||||
assert(
|
||||
@post_serializer.associations.any? do |association|
|
||||
association.key == :blog
|
||||
end
|
||||
|
||||
assert blog_is_present
|
||||
)
|
||||
end
|
||||
|
||||
def test_associations_inheritance
|
||||
inherited_klass = Class.new(PostSerializer)
|
||||
|
||||
assert_equal(PostSerializer._associations, inherited_klass._associations)
|
||||
assert_equal(PostSerializer._reflections, inherited_klass._reflections)
|
||||
end
|
||||
|
||||
def test_associations_inheritance_with_new_association
|
||||
inherited_klass = Class.new(PostSerializer) do
|
||||
has_many :top_comments, serializer: CommentSerializer
|
||||
end
|
||||
expected_associations = PostSerializer._associations.merge(
|
||||
top_comments: {
|
||||
type: :has_many,
|
||||
association_options: {
|
||||
serializer: CommentSerializer
|
||||
}
|
||||
}
|
||||
|
||||
assert(
|
||||
PostSerializer._reflections.all? do |reflection|
|
||||
inherited_klass._reflections.include?(reflection)
|
||||
end
|
||||
)
|
||||
|
||||
assert(
|
||||
inherited_klass._reflections.any? do |reflection|
|
||||
reflection.name == :top_comments
|
||||
end
|
||||
)
|
||||
assert_equal(inherited_klass._associations, expected_associations)
|
||||
end
|
||||
|
||||
def test_associations_custom_keys
|
||||
serializer = PostWithCustomKeysSerializer.new(@post)
|
||||
|
||||
expected_association_keys = []
|
||||
serializer.each_association do |key, serializer, options|
|
||||
expected_association_keys << key
|
||||
end
|
||||
expected_association_keys = serializer.associations.map(&:key)
|
||||
|
||||
assert expected_association_keys.include? :reviews
|
||||
assert expected_association_keys.include? :writer
|
||||
|
||||
Loading…
Reference in New Issue
Block a user