diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index abb1162d..bb7ef131 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -195,12 +195,15 @@ end included_associations = filter(associations.keys) associations.each_with_object({}) do |(name, association), hash| if included_associations.include? name + association_serializer = build_serializer(association) + # we must do this always because even if the current association is not + # embeded in root, it might have its own associations that are embeded in root + hash.merge!(association_serializer.embedded_in_root_associations) {|key, oldval, newval| [newval, oldval].flatten } + if association.embed_in_root? if association.embed_in_root_key? hash = hash[association.embed_in_root_key] ||= {} end - association_serializer = build_serializer(association) - hash.merge!(association_serializer.embedded_in_root_associations) {|key, oldval, newval| [newval, oldval].flatten } serialized_data = association_serializer.serializable_object key = association.root_key diff --git a/test/fixtures/poro.rb b/test/fixtures/poro.rb index 0ed2dafe..17011ba7 100644 --- a/test/fixtures/poro.rb +++ b/test/fixtures/poro.rb @@ -22,9 +22,22 @@ class User < Model end end +class UserInfo < Model + def user + @user ||= User.new(name: 'N1', email: 'E1') + end +end + class Profile < Model end +class Category < Model + def posts + @posts ||= [Post.new(title: 'T1', body: 'B1'), + Post.new(title: 'T2', body: 'B2')] + end +end + class Post < Model def comments @comments ||= [Comment.new(content: 'C1'), @@ -66,6 +79,10 @@ class UserSerializer < ActiveModel::Serializer has_one :profile end +class UserInfoSerializer < ActiveModel::Serializer + has_one :user +end + class ProfileSerializer < ActiveModel::Serializer def description description = object.read_attribute_for_serialization(:description) @@ -75,6 +92,12 @@ class ProfileSerializer < ActiveModel::Serializer attributes :name, :description end +class CategorySerializer < ActiveModel::Serializer + attributes :name + + has_many :posts +end + class PostSerializer < ActiveModel::Serializer attributes :title, :body diff --git a/test/unit/active_model/serializer/has_many_test.rb b/test/unit/active_model/serializer/has_many_test.rb index 4699002d..2e5d212f 100644 --- a/test/unit/active_model/serializer/has_many_test.rb +++ b/test/unit/active_model/serializer/has_many_test.rb @@ -115,6 +115,23 @@ module ActiveModel }, @post_serializer.as_json) end + def test_associations_embedding_ids_including_objects_serialization_when_invoked_from_parent_serializer + @association.embed = :ids + @association.embed_in_root = true + + category = Category.new(name: 'Name 1') + category.instance_variable_set(:@posts, [@post]) + category_serializer = CategorySerializer.new(category) + + assert_equal({ + 'category' => { + name: 'Name 1', + posts: [{ title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } }] + }, + comments: [{ content: 'C1' }, { content: 'C2' }] + }, category_serializer.as_json) + end + def test_associations_embedding_nothing_including_objects_serialization_using_as_json @association.embed = nil @association.embed_in_root = true diff --git a/test/unit/active_model/serializer/has_one_test.rb b/test/unit/active_model/serializer/has_one_test.rb index ff922894..52fac88d 100644 --- a/test/unit/active_model/serializer/has_one_test.rb +++ b/test/unit/active_model/serializer/has_one_test.rb @@ -131,6 +131,20 @@ module ActiveModel }, @user_serializer.as_json) end + def test_associations_embedding_ids_including_objects_serialization_when_invoked_from_parent_serializer + @association.embed = :ids + @association.embed_in_root = true + + user_info = UserInfo.new + user_info.instance_variable_set(:@user, @user) + user_info_serializer = UserInfoSerializer.new(user_info) + + assert_equal({ + 'user_info' => { user: { name: 'Name 1', email: 'mail@server.com', 'profile_id' => @user.profile.object_id } }, + 'profiles' => [{ name: 'N1', description: 'D1' }] + }, user_info_serializer.as_json) + end + def test_associations_embedding_ids_using_a_given_serializer @association.embed = :ids @association.embed_in_root = true