Merge pull request #43 from ctide/master

Add a :root option when defining associations
This commit is contained in:
José Valim 2012-02-22 22:16:21 -08:00
commit 5f0bb6d148
3 changed files with 78 additions and 1 deletions

View File

@ -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.

View File

@ -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

View File

@ -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