From 67c550f2ee06aa6abf8204c3c9aa153bb8eeda35 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 2 Jan 2014 18:24:45 -0200 Subject: [PATCH] Serialize embedding in root deeply nested associations Closes #444 --- lib/active_model/serializer.rb | 19 +++++++++-- test/fixtures/active_record.rb | 6 ++-- .../active_record/active_record_test.rb | 34 ++++++++++--------- .../active_model/serializer/has_many_test.rb | 4 +-- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index fbf4623b..fb6b5ff7 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -149,15 +149,28 @@ end associations.each_with_object({}) do |(name, association), hash| if included_associations.include? name if association.embed_in_root? - hash[association.root_key] = serialize association + association_serializer = build_serializer(association) + hash.merge! association_serializer.embedded_in_root_associations + + serialized_data = association_serializer.serializable_object + key = association.root_key + if hash.has_key?(key) + hash[key].concat(serialized_data).uniq! + else + hash[key] = serialized_data + end end end end end - def serialize(association) + def build_serializer(association) object = send(association.name) - association.build_serializer(object, scope: scope).serializable_object + association.build_serializer(object, scope: scope) + end + + def serialize(association) + build_serializer(association).serializable_object end def serialize_ids(association) diff --git a/test/fixtures/active_record.rb b/test/fixtures/active_record.rb index 9d020b60..ee69cc1b 100644 --- a/test/fixtures/active_record.rb +++ b/test/fixtures/active_record.rb @@ -80,13 +80,13 @@ ARPost.create(title: 'New post', short_tag = post.ar_tags.create(name: 'short') whiny_tag = post.ar_tags.create(name: 'whiny') - happy_tag = post.ar_tags.create(name: 'happy') + happy_tag = ARTag.create(name: 'happy') post.ar_comments.create(body: 'what a dumb post').tap do |comment| - comment.ar_tags.concat short_tag, whiny_tag + comment.ar_tags.concat happy_tag, whiny_tag end post.ar_comments.create(body: 'i liked it').tap do |comment| - comment.ar_tags.concat short_tag, happy_tag + comment.ar_tags.concat happy_tag, short_tag end end diff --git a/test/integration/active_record/active_record_test.rb b/test/integration/active_record/active_record_test.rb index 833795c2..1747fc12 100644 --- a/test/integration/active_record/active_record_test.rb +++ b/test/integration/active_record/active_record_test.rb @@ -14,9 +14,9 @@ module ActiveModel assert_equal({ 'ar_post' => { title: 'New post', body: 'A body!!!', - ar_comments: [{ body: 'what a dumb post', ar_tags: [{ name: 'short' }, { name: 'whiny' }] }, - { body: 'i liked it', ar_tags: [{:name=>"short"}, {:name=>"happy"}] }], - ar_tags: [{ name: 'short' }, { name: 'whiny' }, { name: 'happy' }], + ar_comments: [{ body: 'what a dumb post', ar_tags: [{ name: 'happy' }, { name: 'whiny' }] }, + { body: 'i liked it', ar_tags: [{:name=>"happy"}, {:name=>"short"}] }], + ar_tags: [{ name: 'short' }, { name: 'whiny' }], ar_section: { 'name' => 'ruby' } } }, post_serializer.as_json) @@ -30,7 +30,7 @@ module ActiveModel 'ar_post' => { title: 'New post', body: 'A body!!!', 'ar_comment_ids' => [1, 2], - 'ar_tag_ids' => [1, 2, 3], + 'ar_tag_ids' => [1, 2], 'ar_section_id' => 1 } }, post_serializer.as_json) @@ -41,18 +41,20 @@ module ActiveModel post_serializer = ARPostSerializer.new(@post) embed(ARPostSerializer, embed: :ids, embed_in_root: true) do - assert_equal({ - 'ar_post' => { - title: 'New post', body: 'A body!!!', - 'ar_comment_ids' => [1, 2], - 'ar_tag_ids' => [1, 2, 3], - 'ar_section_id' => 1 - }, - ar_comments: [{ body: 'what a dumb post', ar_tags: [{ name: 'short' }, { name: 'whiny' }] }, - { body: 'i liked it', ar_tags: [{:name=>"short"}, {:name=>"happy"}] }], - ar_tags: [{ name: 'short' }, { name: 'whiny' }, { name: 'happy' }], - 'ar_sections' => [{ 'name' => 'ruby' }] - }, post_serializer.as_json) + embed(ARCommentSerializer, embed: :ids, embed_in_root: true) do + assert_equal({ + 'ar_post' => { + title: 'New post', body: 'A body!!!', + 'ar_comment_ids' => [1, 2], + 'ar_tag_ids' => [1, 2], + 'ar_section_id' => 1 + }, + ar_comments: [{ body: 'what a dumb post', 'ar_tag_ids' => [3, 2] }, + { body: 'i liked it', 'ar_tag_ids' => [3, 1] }], + ar_tags: [{ name: 'happy' }, { name: 'whiny' }, { name: 'short' }], + 'ar_sections' => [{ 'name' => 'ruby' }] + }, post_serializer.as_json) + end end end diff --git a/test/unit/active_model/serializer/has_many_test.rb b/test/unit/active_model/serializer/has_many_test.rb index 9558bd2a..7c94cd67 100644 --- a/test/unit/active_model/serializer/has_many_test.rb +++ b/test/unit/active_model/serializer/has_many_test.rb @@ -130,7 +130,7 @@ module ActiveModel @association.embed_in_root = true @association.serializer_class = Class.new(ActiveModel::Serializer) do def content - 'fake' + object.read_attribute_for_serialization(:content) + '!' end attributes :content @@ -138,7 +138,7 @@ module ActiveModel assert_equal({ 'post' => { title: 'Title 1', body: 'Body 1', 'comment_ids' => @post.comments.map { |c| c.object_id } }, - comments: [{ content: 'fake' }, { content: 'fake' }] + comments: [{ content: 'C1!' }, { content: 'C2!' }] }, @post_serializer.as_json) end