active_model_serializers/test/association_test.rb
Dan Gebhardt 3b1d2faf51 Append an _id or _ids suffix to associations' keys. Embed objects in root according to their serializers' names.
An `_id` suffix will be appended to the name of HasOne associations, while `_ids` will be appended to the singularized name of HasMany associations. Association keys can still be overridden with the `key` option.

Furthermore, objects embedded in the root are now by default named according to their serializer, instead of the key used for their associations.
2012-12-21 15:14:50 -05:00

396 lines
8.6 KiB
Ruby

require "test_helper"
class AssociationTest < ActiveModel::TestCase
def def_serializer(&block)
Class.new(ActiveModel::Serializer, &block)
end
class Model
def initialize(hash={})
@attributes = hash
end
def read_attribute_for_serialization(name)
@attributes[name]
end
def as_json(*)
{ :model => "Model" }
end
def method_missing(meth, *args)
if meth.to_s =~ /^(.*)=$/
@attributes[$1.to_sym] = args[0]
elsif @attributes.key?(meth)
@attributes[meth]
else
super
end
end
end
def setup
@hash = {}
@root_hash = {}
@post = Model.new(:title => "New Post", :body => "Body")
@comment = Model.new(:id => 1, :body => "ZOMG A COMMENT")
@post.comments = [ @comment ]
@post.comment = @comment
@comment_serializer_class = def_serializer do
attributes :id, :body
end
@post_serializer_class = def_serializer do
attributes :title, :body
end
@post_serializer = @post_serializer_class.new(@post, :hash => @root_hash)
end
def include!(key, options={})
@post_serializer.include! key, {
:embed => :ids,
:include => true,
:node => @hash,
:serializer => @comment_serializer_class
}.merge(options)
end
def include_bare!(key, options={})
@post_serializer.include! key, {
:node => @hash,
:serializer => @comment_serializer_class
}.merge(options)
end
class NoDefaults < AssociationTest
def test_include_bang_has_many_associations
include! :comments, :value => @post.comments
assert_equal({
:comment_ids => [ 1 ]
}, @hash)
assert_equal({
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, @root_hash)
end
def test_include_bang_with_embed_false
include! :comments, :value => @post.comments, :embed => false
assert_equal({}, @hash)
assert_equal({}, @root_hash)
end
def test_include_bang_with_embed_ids_include_false
include! :comments, :value => @post.comments, :embed => :ids, :include => false
assert_equal({
:comment_ids => [ 1 ]
}, @hash)
assert_equal({}, @root_hash)
end
def test_include_bang_has_one_associations
include! :comment, :value => @post.comment
assert_equal({
:comment_id => 1
}, @hash)
assert_equal({
:comments => [{ :id => 1, :body => "ZOMG A COMMENT" }]
}, @root_hash)
end
end
class DefaultsTest < AssociationTest
def test_with_default_has_many
@post_serializer_class.class_eval do
has_many :comments
end
include! :comments
assert_equal({
:comment_ids => [ 1 ]
}, @hash)
assert_equal({
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, @root_hash)
end
def test_with_default_has_one
@post_serializer_class.class_eval do
has_one :comment
end
include! :comment
assert_equal({
:comment_id => 1
}, @hash)
assert_equal({
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, @root_hash)
end
def test_with_default_has_many_with_custom_key
@post_serializer_class.class_eval do
has_many :comments, :key => :custom_comments
end
include! :comments
assert_equal({
:custom_comments => [ 1 ]
}, @hash)
assert_equal({
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, @root_hash)
end
def test_with_default_has_one_with_custom_key
@post_serializer_class.class_eval do
has_one :comment, :key => :custom_comment_id
end
include! :comment
assert_equal({
:custom_comment_id => 1
}, @hash)
assert_equal({
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, @root_hash)
end
def test_embed_objects_for_has_many_associations
@post_serializer_class.class_eval do
has_many :comments, :embed => :objects
end
include_bare! :comments
assert_equal({
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, @hash)
assert_equal({}, @root_hash)
end
def test_embed_ids_for_has_many_associations
@post_serializer_class.class_eval do
has_many :comments, :embed => :ids
end
include_bare! :comments
assert_equal({
:comment_ids => [ 1 ]
}, @hash)
assert_equal({}, @root_hash)
end
def test_embed_false_for_has_many_associations
@post_serializer_class.class_eval do
has_many :comments, :embed => false
end
include_bare! :comments
assert_equal({}, @hash)
assert_equal({}, @root_hash)
end
def test_embed_ids_include_true_for_has_many_associations
@post_serializer_class.class_eval do
has_many :comments, :embed => :ids, :include => true
end
include_bare! :comments
assert_equal({
:comment_ids => [ 1 ]
}, @hash)
assert_equal({
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, @root_hash)
end
def test_embed_ids_for_has_one_associations
@post_serializer_class.class_eval do
has_one :comment, :embed => :ids
end
include_bare! :comment
assert_equal({
:comment_id => 1
}, @hash)
assert_equal({}, @root_hash)
end
def test_embed_false_for_has_one_associations
@post_serializer_class.class_eval do
has_one :comment, :embed => false
end
include_bare! :comment
assert_equal({}, @hash)
assert_equal({}, @root_hash)
end
def test_embed_ids_include_true_for_has_one_associations
@post_serializer_class.class_eval do
has_one :comment, :embed => :ids, :include => true
end
include_bare! :comment
assert_equal({
:comment_id => 1
}, @hash)
assert_equal({
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, @root_hash)
end
def test_embed_ids_include_true_does_not_serialize_multiple_times
@post.recent_comment = @comment
@post_serializer_class.class_eval do
has_one :comment, :embed => :ids, :include => true
has_one :recent_comment, :embed => :ids, :include => true, :root => :comments
end
# Count how often the @comment record is serialized.
serialized_times = 0
@comment.class_eval do
define_method :read_attribute_for_serialization, lambda { |name|
serialized_times += 1 if name == :body
super(name)
}
end
include_bare! :comment
include_bare! :recent_comment
assert_equal 1, serialized_times
end
end
class InclusionTest < AssociationTest
def setup
super
comment_serializer_class = @comment_serializer_class
@post_serializer_class.class_eval do
root :post
embed :ids, :include => true
has_many :comments, :serializer => comment_serializer_class
end
end
def test_when_it_is_included
post_serializer = @post_serializer_class.new(
@post, :include => [:comments]
)
json = post_serializer.as_json
assert_equal({
:post => {
:title => "New Post",
:body => "Body",
:comment_ids => [ 1 ]
},
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, json)
end
def test_when_it_is_not_included
post_serializer = @post_serializer_class.new(
@post, :include => []
)
json = post_serializer.as_json
assert_equal({
:post => {
:title => "New Post",
:body => "Body",
:comment_ids => [ 1 ]
}
}, json)
end
def test_when_it_is_excluded
post_serializer = @post_serializer_class.new(
@post, :exclude => [:comments]
)
json = post_serializer.as_json
assert_equal({
:post => {
:title => "New Post",
:body => "Body",
:comment_ids => [ 1 ]
}
}, json)
end
def test_when_it_is_not_excluded
post_serializer = @post_serializer_class.new(
@post, :exclude => []
)
json = post_serializer.as_json
assert_equal({
:post => {
:title => "New Post",
:body => "Body",
:comment_ids => [ 1 ]
},
:comments => [
{ :id => 1, :body => "ZOMG A COMMENT" }
]
}, json)
end
end
end