Skip to content

Commit e290364

Browse files
committed
Encapsulate serialized_associations; test inline associations
1 parent 7cbef1b commit e290364

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

lib/active_model/serializer/associations.rb

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ module Associations
1313
DEFAULT_INCLUDE_TREE = ActiveModel::Serializer::IncludeTree.from_string('*')
1414

1515
included do |base|
16-
base.class_attribute :_reflections
16+
base.class_attribute :serialized_associations, instance_writer: false # @api public: maps association name to 'Reflection' instance
17+
base.serialized_associations ||= {}
18+
base.class_attribute :_reflections, instance_writer: false
1719
base._reflections ||= []
1820

1921
extend ActiveSupport::Autoload
@@ -77,13 +79,16 @@ def has_one(name, options = {}, &block)
7779
def associate(reflection, block)
7880
self._reflections = _reflections.dup
7981

80-
define_method reflection.name do
81-
if block_given?
82-
instance_eval(&block)
83-
else
84-
object.send reflection.name
85-
end
86-
end unless method_defined?(reflection.name)
82+
reflection_name = reflection.name
83+
if block
84+
serialized_associations[reflection_name] = ->(instance) { instance.instance_eval(&block) }
85+
else
86+
serialized_associations[reflection_name] = ->(instance) { instance.object.send(reflection_name) }
87+
end
88+
89+
define_method reflection_name do
90+
serialized_associations[reflection_name].call(self)
91+
end unless method_defined?(reflection_name)
8792

8893
self._reflections << reflection
8994
end

test/serializers/associations_test.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,35 @@ def test_associations_custom_keys
126126
assert expected_association_keys.include? :site
127127
end
128128

129+
class InlineAssociationTestPostSerializer < ActiveModel::Serializer
130+
has_many :comments
131+
has_many :last_comments do
132+
object.comments.last(1)
133+
end
134+
end
135+
136+
def test_virtual_attribute_block
137+
comment1 = ::ARModels::Comment.create!(contents: 'first comment')
138+
comment2 = ::ARModels::Comment.create!(contents: 'last comment')
139+
post = ::ARModels::Post.create!(
140+
title: 'inline association test',
141+
body: 'etc',
142+
comments: [comment1, comment2]
143+
)
144+
actual = serializable(post, adapter: :attributes, serializer: InlineAssociationTestPostSerializer).as_json
145+
expected = {
146+
:comments => [
147+
{ :id => 1, :contents => 'first comment' },
148+
{ :id => 2, :contents => 'last comment' }
149+
],
150+
:last_comments => [
151+
{ :id => 2, :contents => 'last comment' }
152+
]
153+
}
154+
155+
assert_equal expected, actual
156+
end
157+
129158
class NamespacedResourcesTest < Minitest::Test
130159
class ResourceNamespace
131160
Post = Class.new(::Model)

0 commit comments

Comments
 (0)