active_model_serializers/test/serializers/reflection_test.rb
2017-04-22 22:06:59 -05:00

250 lines
9.3 KiB
Ruby

require 'test_helper'
module ActiveModel
class Serializer
class ReflectionTest < ActiveSupport::TestCase
class Blog < ActiveModelSerializers::Model
attributes :id
end
class BlogSerializer < ActiveModel::Serializer
type 'blog'
attributes :id
end
setup do
@expected_meta = { id: 1 }
@expected_links = { self: 'no_uri_validation' }
@empty_links = {}
model_attributes = { blog: Blog.new(@expected_meta) }
@model = Class.new(ActiveModelSerializers::Model) do
attributes(*model_attributes.keys)
def self.name
'TestModel'
end
end.new(model_attributes)
@instance_options = {}
end
def test_reflection_block_with_link_mutates_the_reflection_links
serializer_class = Class.new(ActiveModel::Serializer) do
has_one :blog do
link :self, 'no_uri_validation'
end
end
serializer_instance = serializer_class.new(@model, @instance_options)
# Get Reflection
reflection = serializer_class._reflections.fetch(:blog)
assert_equal @empty_links, reflection.options.fetch(:links)
# Build Association
association = reflection.build_association(serializer_instance, @instance_options)
assert_equal @expected_links, association.links
assert_equal @expected_links, reflection.options.fetch(:links)
end
def test_reflection_block_with_link_block_mutates_the_reflection_links
serializer_class = Class.new(ActiveModel::Serializer) do
has_one :blog do
link :self do
'no_uri_validation'
end
end
end
serializer_instance = serializer_class.new(@model, @instance_options)
# Get Reflection
reflection = serializer_class._reflections.fetch(:blog)
assert_equal @empty_links, reflection.options.fetch(:links)
# Build Association
association = reflection.build_association(serializer_instance, @instance_options)
# Assert before instance_eval link
link = association.links.fetch(:self)
assert_respond_to link, :call
# Assert after instance_eval link
assert_equal @expected_links.fetch(:self), reflection.instance_eval(&link)
assert_respond_to reflection.options.fetch(:links).fetch(:self), :call
end
def test_reflection_block_with_meta_mutates_the_reflection_meta
serializer_class = Class.new(ActiveModel::Serializer) do
has_one :blog do
meta(id: object.blog.id)
end
end
serializer_instance = serializer_class.new(@model, @instance_options)
# Get Reflection
reflection = serializer_class._reflections.fetch(:blog)
assert_nil reflection.options.fetch(:meta)
# Build Association
association = reflection.build_association(serializer_instance, @instance_options)
assert_equal @expected_meta, association.meta
assert_equal @expected_meta, reflection.options.fetch(:meta)
end
def test_reflection_block_with_meta_block_mutates_the_reflection_meta
serializer_class = Class.new(ActiveModel::Serializer) do
has_one :blog do
meta do
{ id: object.blog.id }
end
end
end
serializer_instance = serializer_class.new(@model, @instance_options)
# Get Reflection
reflection = serializer_class._reflections.fetch(:blog)
assert_nil reflection.options.fetch(:meta)
# Build Association
association = reflection.build_association(serializer_instance, @instance_options)
# Assert before instance_eval meta
assert_respond_to association.meta, :call
assert_respond_to reflection.options.fetch(:meta), :call
# Assert after instance_eval meta
assert_equal @expected_meta, reflection.instance_eval(&association.meta)
assert_respond_to reflection.options.fetch(:meta), :call
assert_respond_to association.meta, :call
end
def test_reflection_block_with_meta_in_link_block_mutates_the_reflection_meta
serializer_class = Class.new(ActiveModel::Serializer) do
has_one :blog do
link :self do
meta(id: object.blog.id)
'no_uri_validation'
end
end
end
serializer_instance = serializer_class.new(@model, @instance_options)
# Get Reflection
reflection = serializer_class._reflections.fetch(:blog)
assert_nil reflection.options.fetch(:meta)
assert_equal @empty_links, reflection.options.fetch(:links)
# Build Association
association = reflection.build_association(serializer_instance, @instance_options)
# Assert before instance_eval link meta
assert_nil association.meta
assert_nil reflection.options.fetch(:meta)
link = association.links.fetch(:self)
assert_respond_to link, :call
assert_respond_to reflection.options.fetch(:links).fetch(:self), :call
assert_nil reflection.options.fetch(:meta)
# Assert after instance_eval link
assert_equal 'no_uri_validation', reflection.instance_eval(&link)
assert_equal @expected_meta, reflection.options.fetch(:meta)
assert_nil association.meta
end
# rubocop:disable Metrics/AbcSize
def test_reflection_block_with_meta_block_in_link_block_mutates_the_reflection_meta
serializer_class = Class.new(ActiveModel::Serializer) do
has_one :blog do
link :self do
meta do
{ id: object.blog.id }
end
'no_uri_validation'
end
end
end
serializer_instance = serializer_class.new(@model, @instance_options)
# Get Reflection
reflection = serializer_class._reflections.fetch(:blog)
assert_nil reflection.options.fetch(:meta)
# Build Association
association = reflection.build_association(serializer_instance, @instance_options)
assert_nil association.meta
assert_nil reflection.options.fetch(:meta)
# Assert before instance_eval link
link = association.links.fetch(:self)
assert_nil reflection.options.fetch(:meta)
assert_respond_to link, :call
assert_respond_to association.links.fetch(:self), :call
# Assert after instance_eval link
assert_equal 'no_uri_validation', reflection.instance_eval(&link)
assert_respond_to association.links.fetch(:self), :call
# Assert before instance_eval link meta
assert_respond_to reflection.options.fetch(:meta), :call
assert_nil association.meta
# Assert after instance_eval link meta
assert_equal @expected_meta, reflection.instance_eval(&reflection.options.fetch(:meta))
assert_nil association.meta
end
# rubocop:enable Metrics/AbcSize
def test_no_href_in_vanilla_reflection
serializer_class = Class.new(ActiveModel::Serializer) do
has_one :blog do
link :self do
href 'no_uri_validation'
end
end
end
serializer_instance = serializer_class.new(@model, @instance_options)
# Get Reflection
reflection = serializer_class._reflections.fetch(:blog)
assert_equal @empty_links, reflection.options.fetch(:links)
# Build Association
association = reflection.build_association(serializer_instance, @instance_options)
# Assert before instance_eval link
link = association.links.fetch(:self)
assert_respond_to link, :call
# Assert after instance_eval link
exception = assert_raise(NoMethodError) do
reflection.instance_eval(&link)
end
assert_match(/undefined method `href'/, exception.message)
end
def test_mutating_reflection_block_is_not_thread_safe
serializer_class = Class.new(ActiveModel::Serializer) do
has_one :blog do
meta(id: object.blog.id)
end
end
model1_meta = @expected_meta
# Evaluate reflection meta for model with id 1
serializer_instance = serializer_class.new(@model, @instance_options)
reflection = serializer_class._reflections.fetch(:blog)
assert_nil reflection.options.fetch(:meta)
association = reflection.build_association(serializer_instance, @instance_options)
assert_equal model1_meta, association.meta
assert_equal model1_meta, reflection.options.fetch(:meta)
model2_meta = @expected_meta.merge(id: 2)
# Evaluate reflection meta for model with id 2
@model.blog.id = 2
assert_equal 2, @model.blog.id # sanity check
serializer_instance = serializer_class.new(@model, @instance_options)
reflection = serializer_class._reflections.fetch(:blog)
# WARN: Thread-safety issue
# Before the reflection is evaluated, it has the value from the previous evaluation
assert_equal model1_meta, reflection.options.fetch(:meta)
association = reflection.build_association(serializer_instance, @instance_options)
assert_equal model2_meta, association.meta
assert_equal model2_meta, reflection.options.fetch(:meta)
end
end
end
end