Skip to content

Commit f7f5e29

Browse files
committed
Merge pull request #601 from radanskoric/fix-nested-embed-in-root
Fix for nested embed_in_root when serializer used as part of an association
2 parents d5a993e + ddfd8d2 commit f7f5e29

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

lib/active_model/serializer.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,15 @@ def embedded_in_root_associations
195195
included_associations = filter(associations.keys)
196196
associations.each_with_object({}) do |(name, association), hash|
197197
if included_associations.include? name
198+
association_serializer = build_serializer(association)
199+
# we must do this always because even if the current association is not
200+
# embeded in root, it might have its own associations that are embeded in root
201+
hash.merge!(association_serializer.embedded_in_root_associations) {|key, oldval, newval| [newval, oldval].flatten }
202+
198203
if association.embed_in_root?
199204
if association.embed_in_root_key?
200205
hash = hash[association.embed_in_root_key] ||= {}
201206
end
202-
association_serializer = build_serializer(association)
203-
hash.merge!(association_serializer.embedded_in_root_associations) {|key, oldval, newval| [newval, oldval].flatten }
204207

205208
serialized_data = association_serializer.serializable_object
206209
key = association.root_key

test/fixtures/poro.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,22 @@ def profile
2222
end
2323
end
2424

25+
class UserInfo < Model
26+
def user
27+
@user ||= User.new(name: 'N1', email: 'E1')
28+
end
29+
end
30+
2531
class Profile < Model
2632
end
2733

34+
class Category < Model
35+
def posts
36+
@posts ||= [Post.new(title: 'T1', body: 'B1'),
37+
Post.new(title: 'T2', body: 'B2')]
38+
end
39+
end
40+
2841
class Post < Model
2942
def comments
3043
@comments ||= [Comment.new(content: 'C1'),
@@ -66,6 +79,10 @@ class UserSerializer < ActiveModel::Serializer
6679
has_one :profile
6780
end
6881

82+
class UserInfoSerializer < ActiveModel::Serializer
83+
has_one :user
84+
end
85+
6986
class ProfileSerializer < ActiveModel::Serializer
7087
def description
7188
description = object.read_attribute_for_serialization(:description)
@@ -75,6 +92,12 @@ def description
7592
attributes :name, :description
7693
end
7794

95+
class CategorySerializer < ActiveModel::Serializer
96+
attributes :name
97+
98+
has_many :posts
99+
end
100+
78101
class PostSerializer < ActiveModel::Serializer
79102
attributes :title, :body
80103

test/unit/active_model/serializer/has_many_test.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,23 @@ def test_associations_embedding_ids_including_objects_serialization_using_as_jso
115115
}, @post_serializer.as_json)
116116
end
117117

118+
def test_associations_embedding_ids_including_objects_serialization_when_invoked_from_parent_serializer
119+
@association.embed = :ids
120+
@association.embed_in_root = true
121+
122+
category = Category.new(name: 'Name 1')
123+
category.instance_variable_set(:@posts, [@post])
124+
category_serializer = CategorySerializer.new(category)
125+
126+
assert_equal({
127+
'category' => {
128+
name: 'Name 1',
129+
posts: [{ title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } }]
130+
},
131+
comments: [{ content: 'C1' }, { content: 'C2' }]
132+
}, category_serializer.as_json)
133+
end
134+
118135
def test_associations_embedding_nothing_including_objects_serialization_using_as_json
119136
@association.embed = nil
120137
@association.embed_in_root = true

test/unit/active_model/serializer/has_one_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,20 @@ def test_associations_embedding_ids_including_objects_serialization_using_as_jso
131131
}, @user_serializer.as_json)
132132
end
133133

134+
def test_associations_embedding_ids_including_objects_serialization_when_invoked_from_parent_serializer
135+
@association.embed = :ids
136+
@association.embed_in_root = true
137+
138+
user_info = UserInfo.new
139+
user_info.instance_variable_set(:@user, @user)
140+
user_info_serializer = UserInfoSerializer.new(user_info)
141+
142+
assert_equal({
143+
'user_info' => { user: { name: 'Name 1', email: '[email protected]', 'profile_id' => @user.profile.object_id } },
144+
'profiles' => [{ name: 'N1', description: 'D1' }]
145+
}, user_info_serializer.as_json)
146+
end
147+
134148
def test_associations_embedding_ids_using_a_given_serializer
135149
@association.embed = :ids
136150
@association.embed_in_root = true

0 commit comments

Comments
 (0)