From 4bdf44a03b47ad79b5cf9c6224e87bbb1d61552b Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Mon, 30 Nov 2015 17:47:12 -0600 Subject: [PATCH] Encapsulate serialized_associations; test inline associations --- lib/active_model/serializer/associations.rb | 21 +++++++++------ test/serializers/associations_test.rb | 29 +++++++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/lib/active_model/serializer/associations.rb b/lib/active_model/serializer/associations.rb index a07b52ca5..0842b9c33 100644 --- a/lib/active_model/serializer/associations.rb +++ b/lib/active_model/serializer/associations.rb @@ -13,7 +13,9 @@ module Associations DEFAULT_INCLUDE_TREE = ActiveModel::Serializer::IncludeTree.from_string('*') included do |base| - base.class_attribute :_reflections + base.class_attribute :serialized_associations, instance_writer: false # @api public: maps association name to 'Reflection' instance + base.serialized_associations ||= {} + base.class_attribute :_reflections, instance_writer: false base._reflections ||= [] extend ActiveSupport::Autoload @@ -77,13 +79,16 @@ def has_one(name, options = {}, &block) def associate(reflection, block) self._reflections = _reflections.dup - define_method reflection.name do - if block_given? - instance_eval(&block) - else - object.send reflection.name - end - end unless method_defined?(reflection.name) + reflection_name = reflection.name + if block + serialized_associations[reflection_name] = ->(instance) { instance.instance_eval(&block) } + else + serialized_associations[reflection_name] = ->(instance) { instance.object.send(reflection_name) } + end + + define_method reflection_name do + serialized_associations[reflection_name].call(self) + end unless method_defined?(reflection_name) self._reflections << reflection end diff --git a/test/serializers/associations_test.rb b/test/serializers/associations_test.rb index 205cfcc88..81380c7c7 100644 --- a/test/serializers/associations_test.rb +++ b/test/serializers/associations_test.rb @@ -126,6 +126,35 @@ def test_associations_custom_keys assert expected_association_keys.include? :site end + class InlineAssociationTestPostSerializer < ActiveModel::Serializer + has_many :comments + has_many :last_comments do + object.comments.last(1) + end + end + + def test_virtual_attribute_block + comment1 = ::ARModels::Comment.create!(contents: 'first comment') + comment2 = ::ARModels::Comment.create!(contents: 'last comment') + post = ::ARModels::Post.create!( + title: 'inline association test', + body: 'etc', + comments: [comment1, comment2] + ) + actual = serializable(post, adapter: :attributes, serializer: InlineAssociationTestPostSerializer).as_json + expected = { + :comments => [ + { :id => 1, :contents => 'first comment' }, + { :id => 2, :contents => 'last comment' } + ], + :last_comments => [ + { :id => 2, :contents => 'last comment' } + ] + } + + assert_equal expected, actual + end + class NamespacedResourcesTest < Minitest::Test class ResourceNamespace Post = Class.new(::Model)