From f17e4cde3944e306ac2662e1041055f4343973f3 Mon Sep 17 00:00:00 2001 From: ctide Date: Wed, 22 Feb 2012 19:35:10 -0800 Subject: [PATCH] Add a :root option to associations, which enables you to define what the root level key will be for the associated objects. --- README.markdown | 24 +++++++++++++++++ lib/active_model/serializer.rb | 6 ++++- test/serializer_test.rb | 49 ++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 5062da34..f07e7905 100644 --- a/README.markdown +++ b/README.markdown @@ -163,6 +163,30 @@ Assuming that the comments also `has_many :tags`, you will get a JSON like this: { "id": 3, "name": "happy" } ] } + +You can also specify a different root for the embedded objects than the key used to reference them, such as like this: + + class PostSerializer < ApplicationSerializer + embed :ids, :include => true + + attributes :id, :title, :body + has_many :comments, :key => :comment_ids, :root => :comment_objects + end + +This would generate JSON that would look like this: + + { + "post": { + "id": 1, + "title": "New post", + "body": "A body!", + "comment_ids": [ 1 ] + }, + "comment_objects": [ + { "id": 1, "body": "what a dumb post" } + ] + } + **NOTE**: The `embed :ids` mechanism is primary useful for clients that process data in bulk and load it into a local store. For these clients, the ability to easily see all of the data per type, rather than having to recursively scan the data looking for information, is extremely useful. diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index ac0abf7e..d85b9500 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -146,6 +146,10 @@ module ActiveModel option(:key) || @name end + def root + option(:root) || plural_key + end + def name option(:name) || @name end @@ -454,7 +458,7 @@ module ActiveModel node[association.key] = association.serialize_ids if association.embed_in_root? - merge_association hash, association.plural_key, association.serialize_many, unique_values + merge_association hash, association.root, association.serialize_many, unique_values end elsif association.embed_objects? node[association.key] = association.serialize diff --git a/test/serializer_test.rb b/test/serializer_test.rb index c5cf5b86..be562f31 100644 --- a/test/serializer_test.rb +++ b/test/serializer_test.rb @@ -702,7 +702,56 @@ class SerializerTest < ActiveModel::TestCase expected = serializer_class.new(post).as_json assert_equal expected, hash_object end + + def test_embed_ids_include_true_with_root + serializer_class = post_serializer + serializer_class.class_eval do + root :post + embed :ids, :include => true + has_many :comments, :key => :comment_ids, :root => :comments + has_one :author, :serializer => DefaultUserSerializer, :key => :author_id, :root => :author + end + + post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com") + comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)] + post.comments = comments + + serializer = serializer_class.new(post) + + assert_equal({ + :post => { + :title => "New Post", + :body => "Body of new post", + :comment_ids => [1, 2], + :author_id => nil + }, + :comments => [ + { :title => "Comment1" }, + { :title => "Comment2" } + ], + :author => [] + }, serializer.as_json) + + post.author = User.new(:id => 1) + + serializer = serializer_class.new(post) + + assert_equal({ + :post => { + :title => "New Post", + :body => "Body of new post", + :comment_ids => [1, 2], + :author_id => 1 + }, + :comments => [ + { :title => "Comment1" }, + { :title => "Comment2" } + ], + :author => [{ :first_name => "Jose", :last_name => "Valim" }] + }, serializer.as_json) + end + # the point of this test is to illustrate that deeply nested serializers # still side-load at the root. def test_embed_with_include_inserts_at_root