active_model_serializers/test/serializer_test.rb
2013-05-30 15:25:06 -06:00

1522 lines
36 KiB
Ruby

require "test_helper"
require "test_fakes"
class SerializerTest < ActiveModel::TestCase
def test_scope_works_correct
serializer = ActiveModel::Serializer.new :foo, scope: :bar
assert_equal serializer.scope, :bar
end
def test_attributes
user = User.new
user_serializer = DefaultUserSerializer.new(user, {})
hash = user_serializer.as_json
assert_equal({
default_user: { first_name: "Jose", last_name: "Valim" }
}, hash)
end
def test_attributes_method
user = User.new
user_serializer = UserSerializer.new(user, scope: {})
hash = user_serializer.as_json
assert_equal({
user: { first_name: "Jose", last_name: "Valim", ok: true }
}, hash)
end
def test_attributes_method_specifying_keys
user = User.new
user_serializer = UserAttributesWithKeySerializer.new(user, scope: {})
hash = user_serializer.as_json
assert_equal({
user_attributes_with_key: { f_name: "Jose", l_name: "Valim", ok: true }
}, hash)
end
def test_attributes_method_specifying_some_keys
user = User.new
user_serializer = UserAttributesWithSomeKeySerializer.new(user, scope: {})
hash = user_serializer.as_json
assert_equal({
user_attributes_with_some_key: { first_name: "Jose", l_name: "Valim", ok: true }
}, hash)
end
def test_attributes_method_with_unsymbolizable_key
user = User.new
user_serializer = UserAttributesWithUnsymbolizableKeySerializer.new(user, scope: {})
hash = user_serializer.as_json
assert_equal({
user_attributes_with_unsymbolizable_key: { first_name: "Jose", :"last-name" => "Valim", ok: true }
}, hash)
end
def test_attribute_method_with_name_as_serializer_prefix
object = SomeObject.new("something")
object_serializer = SomeSerializer.new(object, {})
hash = object_serializer.as_json
assert_equal({
some: { some: "something" }
}, hash)
end
def test_serializer_receives_scope
user = User.new
user_serializer = UserSerializer.new(user, scope: { scope: true })
hash = user_serializer.as_json
assert_equal({
user: {
first_name: "Jose",
last_name: "Valim",
ok: true,
scope: true
}
}, hash)
end
def test_serializer_receives_url_options
user = User.new
user_serializer = UserSerializer.new(user, url_options: { host: "test.local" })
assert_equal({ host: "test.local" }, user_serializer.url_options)
end
def test_serializer_returns_empty_hash_without_url_options
user = User.new
user_serializer = UserSerializer.new(user)
assert_equal({}, user_serializer.url_options)
end
def test_pretty_accessors
user = User.new
user.superuser = true
user_serializer = MyUserSerializer.new(user)
hash = user_serializer.as_json
assert_equal({
my_user: {
first_name: "Jose", last_name: "Valim", super_user: true
}
}, hash)
end
def test_has_many
user = User.new
post = Post.new(title: "New Post", body: "Body of new post", email: "tenderlove@tenderlove.com")
comments = [Comment.new(title: "Comment1"), Comment.new(title: "Comment2")]
post.comments = comments
post_serializer = PostSerializer.new(post, scope: user)
assert_equal({
post: {
title: "New Post",
body: "Body of new post",
comments: [
{ title: "Comment1" },
{ title: "Comment2" }
]
}
}, post_serializer.as_json)
end
def test_conditionally_included_associations
user = User.new
post = Post.new(title: "New Post", body: "Body of new post", email: "tenderlove@tenderlove.com")
comments = [Comment.new(title: "Comment1"), Comment.new(title: "Comment2")]
post.comments = comments
post_serializer = PostWithConditionalCommentsSerializer.new(post, scope: user)
# comments enabled
post.comments_disabled = false
assert_equal({
post: {
title: "New Post",
body: "Body of new post",
comments: [
{ title: "Comment1" },
{ title: "Comment2" }
]
}
}, post_serializer.as_json)
# comments disabled
post.comments_disabled = true
assert_equal({
post: {
title: "New Post",
body: "Body of new post"
}
}, post_serializer.as_json)
end
def test_conditionally_included_associations_and_attributes
user = User.new
post = Post.new(title: "New Post", body: "Body of new post", author: 'Sausage King', email: "tenderlove@tenderlove.com")
comments = [Comment.new(title: "Comment1"), Comment.new(title: "Comment2")]
post.comments = comments
post_serializer = PostWithMultipleConditionalsSerializer.new(post, scope: user)
# comments enabled
post.comments_disabled = false
assert_equal({
post: {
title: "New Post",
body: "Body of new post",
comments: [
{ title: "Comment1" },
{ title: "Comment2" }
]
}
}, post_serializer.as_json)
# comments disabled
post.comments_disabled = true
assert_equal({
post: {
title: "New Post",
body: "Body of new post"
}
}, post_serializer.as_json)
# superuser - should see author
user.superuser = true
assert_equal({
post: {
title: "New Post",
body: "Body of new post",
author: "Sausage King"
}
}, post_serializer.as_json)
end
def test_has_one
user = User.new
blog = Blog.new
blog.author = user
json = BlogSerializer.new(blog, scope: user).as_json
assert_equal({
blog: {
author: {
first_name: "Jose",
last_name: "Valim"
}
}
}, json)
end
def test_overridden_associations
author_serializer = Class.new(ActiveModel::Serializer) do
attributes :first_name
end
blog_serializer = Class.new(ActiveModel::Serializer) do
def person
object.author
end
has_one :person, serializer: author_serializer
end
user = User.new
blog = Blog.new
blog.author = user
json = blog_serializer.new(blog, scope: user).as_json
assert_equal({
person: {
first_name: "Jose"
}
}, json)
end
def post_serializer
Class.new(ActiveModel::Serializer) do
attributes :title, :body
has_many :comments, serializer: CommentSerializer
has_one :author, serializer: DefaultUserSerializer
end
end
def test_associations_with_nil_association
user = User.new
blog = Blog.new
json = BlogSerializer.new(blog, scope: user).as_json
assert_equal({
blog: { author: nil }
}, json)
serializer = Class.new(BlogSerializer) do
root :blog
end
json = serializer.new(blog, scope: user).as_json
assert_equal({ blog: { author: nil } }, json)
end
def test_custom_root
user = User.new
blog = Blog.new
serializer = Class.new(BlogSerializer) do
root :my_blog
end
assert_equal({ my_blog: { author: nil } }, serializer.new(blog, scope: user).as_json)
end
def test_nil_root_object
user = User.new
blog = nil
serializer = Class.new(BlogSerializer) do
root false
end
assert_equal(nil, serializer.new(blog, scope: user).as_json)
end
def test_custom_root_with_nil_root_object
user = User.new
blog = nil
serializer = Class.new(BlogSerializer) do
root :my_blog
end
assert_equal({ my_blog: nil }, serializer.new(blog, scope: user).as_json)
end
def test_false_root
user = User.new
blog = Blog.new
serializer = Class.new(BlogSerializer) do
root false
end
another_serializer = Class.new(BlogSerializer) do
self.root = false
end
assert_equal({ author: nil }, serializer.new(blog, scope: user).as_json)
assert_equal({ author: nil }, another_serializer.new(blog, scope: user).as_json)
# test inherited false root
serializer = Class.new(serializer)
assert_equal({ author: nil }, serializer.new(blog, scope: user).as_json)
end
def test_true_root
blog = Blog.new
assert_equal({
blog_with_root: {
author: nil,
}
}, BlogWithRootSerializer.new(blog).as_json)
end
def test_root_false_on_load_active_model_serializers
begin
ActiveSupport.on_load(:active_model_serializers) do
self.root = false
end
blog = Blog.new
serializer = BlogSerializer.new(blog)
assert_equal({ author: nil }, serializer.as_json)
ensure
ActiveSupport.on_load(:active_model_serializers) do
self.root = nil
end
end
end
def test_embed_ids
serializer = post_serializer
serializer.class_eval do
root :post
embed :ids
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.new(post)
assert_equal({
post: {
title: "New Post",
body: "Body of new post",
comment_ids: [1, 2],
author_id: nil
}
}, serializer.as_json)
end
def test_embed_ids_include_true
serializer_class = post_serializer
serializer_class.class_eval do
root :post
embed :ids, include: true
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" }
],
authors: []
}, 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" }
],
authors: [{ first_name: "Jose", last_name: "Valim" }]
}, serializer.as_json)
end
def test_methods_take_priority_over_associations
post_serializer = Class.new(ActiveModel::Serializer) do
attributes :title
has_many :comments
embed :ids
def comments
object.comments[0,1]
end
end
post = Post.new(title: "My Post")
comments = [Comment.new(title: "Comment1", id: 1), Comment.new(title: "Comment2", id: 2)]
post.comments = comments
post.class_eval do
define_method :comment_ids, lambda {
self.comments.map { |c| c.read_attribute_for_serialization(:id) }
}
end
json = post_serializer.new(post).as_json
assert_equal({
title: "My Post",
comment_ids: [1]
}, json)
end
def test_methods_take_priority_over_associations_and_call_the_appropriate_id_method
comment_serializer = Class.new(ActiveModel::Serializer) do
def id
"OMG"
end
end
post_serializer = Class.new(ActiveModel::Serializer) do
attributes :title
has_many :comments, serializer: comment_serializer
embed :ids
def comments
object.comments[0,1]
end
end
post = Post.new(title: "My Post")
comments = [Comment.new(title: "Comment1", id: 1), Comment.new(title: "Comment2", id: 2)]
post.comments = comments
post.class_eval do
define_method :comment_ids, lambda {
self.comments.map { |c| c.read_attribute_for_serialization(:id) }
}
end
json = post_serializer.new(post).as_json
assert_equal({
title: "My Post",
comment_ids: ["OMG"]
}, json)
end
def test_embed_objects
serializer = post_serializer
serializer.class_eval do
root :post
embed :objects
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.new(post)
assert_equal({
post: {
title: "New Post",
body: "Body of new post",
author: nil,
comments: [
{ title: "Comment1" },
{ title: "Comment2" }
]
}
}, serializer.as_json)
end
def test_sets_can_be_serialized
post1 = Post.new(title: "Post1", author: "Author1", id: 1)
post2 = Post.new(title: "Post2", author: "Author2", id: 2)
set = Set.new
set << post1
set << post2
serializer = set.active_model_serializer.new set, each_serializer: CustomPostSerializer
as_json = serializer.as_json
assert_equal 2, as_json.size
assert as_json.include?({ title: "Post1" })
assert as_json.include?({ title: "Post2" })
end
def test_associations_with_as
posts = [
Post.new(title: 'First Post', body: 'text'),
Post.new(title: 'Second Post', body: 'text')
]
user = User.new
custom_blog = CustomBlog.new
custom_blog.public_posts = posts
custom_blog.public_user = user
serializer = CustomBlogSerializer.new(custom_blog, scope: { scope: true })
assert_equal({
custom_blog: {
posts: [
{title: 'First Post', body: 'text', comments: []},
{title: 'Second Post', body: 'text', comments: []}
],
user: {
first_name: "Jose",
last_name: "Valim", ok: true,
scope: true
}
}
}, serializer.as_json)
end
def test_implicity_detection_for_association_serializers
implicit_serializer = Class.new(ActiveModel::Serializer) do
root :custom_blog
const_set(:UserSerializer, UserSerializer)
const_set(:PostSerializer, PostSerializer)
has_many :public_posts, key: :posts
has_one :public_user, key: :user
end
posts = [
Post.new(title: 'First Post', body: 'text', comments: []),
Post.new(title: 'Second Post', body: 'text', comments: [])
]
user = User.new
custom_blog = CustomBlog.new
custom_blog.public_posts = posts
custom_blog.public_user = user
serializer = implicit_serializer.new(custom_blog, scope: { scope: true })
assert_equal({
custom_blog: {
posts: [
{title: 'First Post', body: 'text', comments: []},
{title: 'Second Post', body: 'text', comments: []}
],
user: {
first_name: "Jose",
last_name: "Valim", ok: true,
scope: true
}
}
}, serializer.as_json)
end
def test_attribute_key
serializer_class = Class.new(ActiveModel::Serializer) do
root :user
attribute :first_name, key: :firstName
attribute :last_name, key: :lastName
attribute :password
end
serializer = serializer_class.new(User.new)
assert_equal({
user: {
firstName: "Jose",
lastName: "Valim",
password: "oh noes yugive my password"
}
}, serializer.as_json)
end
def setup_model
Class.new do
class << self
def columns_hash
{ "name" => Struct.new(:type).new(:string), "age" => Struct.new(:type).new(:integer) }
end
def reflect_on_association(name)
case name
when :posts
Struct.new(:macro, :name).new(:has_many, :posts)
when :parent
Struct.new(:macro, :name).new(:belongs_to, :parent)
end
end
end
end
end
def test_schema
model = setup_model
serializer = Class.new(ActiveModel::Serializer) do
class << self; self; end.class_eval do
define_method(:model_class) do model end
end
# Computed attributes (not real columns or associations).
def can_edit; end
def can_view; end
def drafts; end
attributes :name, :age, { can_edit: :boolean }, :can_view
has_many :posts, serializer: Class.new
has_many :drafts, serializer: Class.new
has_one :parent, serializer: Class.new
end
assert_equal serializer.schema, {
attributes: { name: :string, age: :integer, can_edit: :boolean, can_view: nil },
associations: {
posts: { has_many: :posts },
drafts: nil,
parent: { belongs_to: :parent }
}
}
end
def test_schema_with_as
model = setup_model
serializer = Class.new(ActiveModel::Serializer) do
class << self; self; end.class_eval do
define_method(:model_class) do model end
end
attributes :name, :age
has_many :posts, key: :my_posts, serializer: Class.new
has_one :parent, key: :my_parent, serializer: Class.new
end
assert_equal serializer.schema, {
attributes: { name: :string, age: :integer },
associations: {
my_posts: { has_many: :posts },
my_parent: { belongs_to: :parent }
}
}
end
def test_embed_id_for_has_one
author_serializer = Class.new(ActiveModel::Serializer)
serializer_class = Class.new(ActiveModel::Serializer) do
embed :ids
root :post
attributes :title, :body
has_one :author, serializer: author_serializer
end
post_class = Class.new(Model) do
attr_accessor :author
end
author_class = Class.new(Model)
post = post_class.new(title: "New Post", body: "It's a new post!")
author = author_class.new(id: 5)
post.author = author
hash = serializer_class.new(post)
assert_equal({
post: {
title: "New Post",
body: "It's a new post!",
author_id: 5
}
}, hash.as_json)
end
def test_embed_id_for_has_one_overriding_associated_id
author_serializer = Class.new(ActiveModel::Serializer) do
def id
"OMG"
end
end
serializer_class = Class.new(ActiveModel::Serializer) do
embed :ids
root :post
attributes :title, :body
has_one :author, serializer: author_serializer
end
post_class = Class.new(Model) do
attr_accessor :author
end
author_class = Class.new(Model)
post = post_class.new(title: "New Post", body: "It's a new post!")
author = author_class.new(id: 5)
post.author = author
hash = serializer_class.new(post)
assert_equal({
post: {
title: "New Post",
body: "It's a new post!",
author_id: "OMG"
}
}, hash.as_json)
end
def test_embed_objects_for_has_one
author_serializer = Class.new(ActiveModel::Serializer) do
attributes :id, :name
end
serializer_class = Class.new(ActiveModel::Serializer) do
root :post
attributes :title, :body
has_one :author, serializer: author_serializer
end
post_class = Class.new(Model) do
attr_accessor :author
end
author_class = Class.new(Model)
post = post_class.new(title: "New Post", body: "It's a new post!")
author = author_class.new(id: 5, name: "Tom Dale")
post.author = author
hash = serializer_class.new(post)
assert_equal({
post: {
title: "New Post",
body: "It's a new post!",
author: { id: 5, name: "Tom Dale" }
}
}, hash.as_json)
end
def test_root_provided_in_options
author_serializer = Class.new(ActiveModel::Serializer) do
attributes :id, :name
end
serializer_class = Class.new(ActiveModel::Serializer) do
root :post
attributes :title, :body
has_one :author, serializer: author_serializer
end
post_class = Class.new(Model) do
attr_accessor :author
end
author_class = Class.new(Model)
post = post_class.new(title: "New Post", body: "It's a new post!")
author = author_class.new(id: 5, name: "Tom Dale")
post.author = author
assert_equal({
blog_post: {
title: "New Post",
body: "It's a new post!",
author: { id: 5, name: "Tom Dale" }
}
}, serializer_class.new(post, root: :blog_post).as_json)
assert_equal({
title: "New Post",
body: "It's a new post!",
author: { id: 5, name: "Tom Dale" }
}, serializer_class.new(post, root: false).as_json)
assert_equal({
blog_post: {
title: "New Post",
body: "It's a new post!",
author: { id: 5, name: "Tom Dale" }
}
}, serializer_class.new(post).as_json(root: :blog_post))
assert_equal({
title: "New Post",
body: "It's a new post!",
author: { id: 5, name: "Tom Dale" }
}, serializer_class.new(post).as_json(root: false))
end
def test_serializer_has_access_to_root_object
hash_object = nil
author_serializer = Class.new(ActiveModel::Serializer) do
attributes :id, :name
define_method :serializable_hash do
hash_object = @options[:hash]
super()
end
end
serializer_class = Class.new(ActiveModel::Serializer) do
root :post
attributes :title, :body
has_one :author, serializer: author_serializer
end
post_class = Class.new(Model) do
attr_accessor :author
end
author_class = Class.new(Model)
post = post_class.new(title: "New Post", body: "It's a new post!")
author = author_class.new(id: 5, name: "Tom Dale")
post.author = author
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
tag_serializer = Class.new(ActiveModel::Serializer) do
attributes :id, :name
end
comment_serializer = Class.new(ActiveModel::Serializer) do
embed :ids, include: true
attributes :id, :body
has_many :tags, serializer: tag_serializer
end
post_serializer = Class.new(ActiveModel::Serializer) do
embed :ids, include: true
attributes :id, :title, :body
has_many :comments, serializer: comment_serializer
end
post_class = Class.new(Model) do
attr_accessor :comments
define_method :active_model_serializer do
post_serializer
end
end
comment_class = Class.new(Model) do
attr_accessor :tags
end
tag_class = Class.new(Model)
post = post_class.new(title: "New Post", body: "NEW POST", id: 1)
comment1 = comment_class.new(body: "EWOT", id: 1)
comment2 = comment_class.new(body: "YARLY", id: 2)
tag1 = tag_class.new(name: "lolcat", id: 1)
tag2 = tag_class.new(name: "nyancat", id: 2)
tag3 = tag_class.new(name: "violetcat", id: 3)
post.comments = [comment1, comment2]
comment1.tags = [tag1, tag3]
comment2.tags = [tag1, tag2]
actual = ActiveModel::ArraySerializer.new([post], root: :posts).as_json
assert_equal({
posts: [
{ title: "New Post", body: "NEW POST", id: 1, comment_ids: [1,2] }
],
comments: [
{ body: "EWOT", id: 1, tag_ids: [1,3] },
{ body: "YARLY", id: 2, tag_ids: [1,2] }
],
tags: [
{ name: "lolcat", id: 1 },
{ name: "violetcat", id: 3 },
{ name: "nyancat", id: 2 }
]
}, actual)
end
def test_can_customize_attributes
serializer = Class.new(ActiveModel::Serializer) do
attributes :title, :body
def title
object.title.upcase
end
end
klass = Class.new do
def read_attribute_for_serialization(name)
{ title: "New post!", body: "First post body" }[name]
end
def title
read_attribute_for_serialization(:title)
end
def body
read_attribute_for_serialization(:body)
end
end
object = klass.new
actual = serializer.new(object, root: :post).as_json
assert_equal({
post: {
title: "NEW POST!",
body: "First post body"
}
}, actual)
end
def test_can_customize_attributes_with_read_attributes
serializer = Class.new(ActiveModel::Serializer) do
attributes :title, :body
def read_attribute_for_serialization(name)
{ title: "New post!", body: "First post body" }[name]
end
end
actual = serializer.new(Object.new, root: :post).as_json
assert_equal({
post: {
title: "New post!",
body: "First post body"
}
}, actual)
end
def test_active_support_on_load_hooks_fired
loaded = nil
ActiveSupport.on_load(:active_model_serializers) do
loaded = self
end
assert_equal ActiveModel::Serializer, loaded
end
def tests_query_attributes_strip_question_mark
todo = Class.new do
def overdue?
true
end
def read_attribute_for_serialization(name)
send name
end
end
serializer = Class.new(ActiveModel::Serializer) do
attribute :overdue?
end
actual = serializer.new(todo.new).as_json
assert_equal({
overdue: true
}, actual)
end
def tests_query_attributes_allow_key_option
todo = Class.new do
def overdue?
true
end
def read_attribute_for_serialization(name)
send name
end
end
serializer = Class.new(ActiveModel::Serializer) do
attribute :overdue?, key: :foo
end
actual = serializer.new(todo.new).as_json
assert_equal({
foo: true
}, actual)
end
def tests_can_handle_polymorphism
email_serializer = Class.new(ActiveModel::Serializer) do
attributes :subject, :body
end
email_class = Class.new(Model) do
def self.to_s
"Email"
end
define_method :active_model_serializer do
email_serializer
end
end
attachment_serializer = Class.new(ActiveModel::Serializer) do
attributes :name, :url
has_one :attachable, polymorphic: true
end
email = email_class.new subject: 'foo', body: 'bar'
attachment = Attachment.new name: 'logo.png', url: 'http://example.com/logo.png', attachable: email
actual = attachment_serializer.new(attachment, {}).as_json
assert_equal({
name: 'logo.png',
url: 'http://example.com/logo.png',
attachable: {
type: :email,
email: { subject: 'foo', body: 'bar' }
}
}, actual)
end
def test_can_handle_polymoprhic_ids
email_serializer = Class.new(ActiveModel::Serializer) do
attributes :subject, :body
end
email_class = Class.new(Model) do
def self.to_s
"Email"
end
define_method :active_model_serializer do
email_serializer
end
end
attachment_serializer = Class.new(ActiveModel::Serializer) do
embed :ids
attributes :name, :url
has_one :attachable, polymorphic: true
end
email = email_class.new id: 1
attachment = Attachment.new name: 'logo.png', url: 'http://example.com/logo.png', attachable: email
actual = attachment_serializer.new(attachment, {}).as_json
assert_equal({
name: 'logo.png',
url: 'http://example.com/logo.png',
attachable: {
type: :email,
id: 1
}
}, actual)
end
def test_polymorphic_associations_are_included_at_root
email_serializer = Class.new(ActiveModel::Serializer) do
attributes :subject, :body, :id
end
email_class = Class.new(Model) do
def self.to_s
"Email"
end
define_method :active_model_serializer do
email_serializer
end
end
attachment_serializer = Class.new(ActiveModel::Serializer) do
root :attachment
embed :ids, include: true
attributes :name, :url
has_one :attachable, polymorphic: true
end
email = email_class.new id: 1, subject: "Hello", body: "World"
attachment = Attachment.new name: 'logo.png', url: 'http://example.com/logo.png', attachable: email
actual = attachment_serializer.new(attachment, {}).as_json
assert_equal({
attachment: {
name: 'logo.png',
url: 'http://example.com/logo.png',
attachable: {
type: :email,
id: 1
}},
emails: [{
id: 1,
subject: "Hello",
body: "World"
}]
}, actual)
end
def test_multiple_polymorphic_associations
email_serializer = Class.new(ActiveModel::Serializer) do
attributes :subject, :body, :id
end
orange_serializer = Class.new(ActiveModel::Serializer) do
embed :ids, include: true
attributes :plu, :id
has_one :readable, polymorphic: true
end
email_class = Class.new(Model) do
def self.to_s
"Email"
end
define_method :active_model_serializer do
email_serializer
end
end
orange_class = Class.new(Model) do
def self.to_s
"Orange"
end
def readable
@attributes[:readable]
end
define_method :active_model_serializer do
orange_serializer
end
end
attachment_serializer = Class.new(ActiveModel::Serializer) do
root :attachment
embed :ids, include: true
attributes :name, :url
has_one :attachable, polymorphic: true
has_one :readable, polymorphic: true
has_one :edible, polymorphic: true
end
email = email_class.new id: 1, subject: "Hello", body: "World"
orange = orange_class.new id: 1, plu: "3027", readable: email
attachment = Attachment.new({
name: 'logo.png',
url: 'http://example.com/logo.png',
attachable: email,
readable: email,
edible: orange
})
actual = attachment_serializer.new(attachment, {}).as_json
assert_equal({
emails: [{
subject: "Hello",
body: "World",
id: 1
}],
oranges: [{
plu: "3027",
id: 1,
readable: { type: :email, id: 1 }
}],
attachment: {
name: 'logo.png',
url: 'http://example.com/logo.png',
attachable: { type: :email, id: 1 },
readable: { type: :email, id: 1 },
edible: { type: :orange, id: 1 }
}
}, actual)
end
def test_raises_an_error_when_a_child_serializer_includes_associations_when_the_source_doesnt
attachment_serializer = Class.new(ActiveModel::Serializer) do
attributes :name
end
fruit_serializer = Class.new(ActiveModel::Serializer) do
embed :ids, include: true
has_one :attachment, serializer: attachment_serializer
attribute :color
end
banana_class = Class.new Model do
def self.to_s
'banana'
end
def attachment
@attributes[:attachment]
end
define_method :active_model_serializer do
fruit_serializer
end
end
strawberry_class = Class.new Model do
def self.to_s
'strawberry'
end
def attachment
@attributes[:attachment]
end
define_method :active_model_serializer do
fruit_serializer
end
end
smoothie = Class.new do
attr_reader :base, :flavor
def initialize(base, flavor)
@base, @flavor = base, flavor
end
end
smoothie_serializer = Class.new(ActiveModel::Serializer) do
root false
embed :ids, include: true
has_one :base, polymorphic: true
has_one :flavor, polymorphic: true
end
banana_attachment = Attachment.new({
name: 'banana_blending.md',
id: 3,
})
strawberry_attachment = Attachment.new({
name: 'strawberry_cleaning.doc',
id: 4
})
banana = banana_class.new color: "yellow", id: 1, attachment: banana_attachment
strawberry = strawberry_class.new color: "red", id: 2, attachment: strawberry_attachment
smoothie = smoothie_serializer.new(smoothie.new(banana, strawberry))
assert_raise ActiveModel::Serializer::IncludeError do
smoothie.as_json
end
end
def tests_includes_does_not_include_nil_polymoprhic_associations
post_serializer = Class.new(ActiveModel::Serializer) do
root :post
embed :ids, include: true
has_one :author, polymorphic: true
attributes :title
end
post = Post.new(title: 'Foo')
actual = post_serializer.new(post).as_json
assert_equal({
post: {
title: 'Foo',
author: nil
}
}, actual)
end
def test_meta_key_serialization
tag_serializer = Class.new(ActiveModel::Serializer) do
attributes :name
end
tag_class = Class.new(Model) do
def name
@attributes[:name]
end
define_method :active_model_serializer do
tag_serializer
end
end
serializable_array = Class.new(Array)
array = serializable_array.new
array << tag_class.new(name: 'Rails')
array << tag_class.new(name: 'Sinatra')
actual = array.active_model_serializer.new(array, root: :tags, meta: {total: 10}).as_json
assert_equal({
meta: {
total: 10,
},
tags: [
{ name: "Rails" },
{ name: "Sinatra" },
]
}, actual)
actual = array.active_model_serializer.new(array, root: :tags, meta: {total: 10}, meta_key: 'meta_object').as_json
assert_equal({
meta_object: {
total: 10,
},
tags: [
{ name: "Rails" },
{ name: "Sinatra" },
]
}, actual)
end
def test_inheritance_does_not_used_cached_attributes
parent = Class.new(ActiveModel::Serializer) do
attributes :title
end
child = Class.new(parent) do
attributes :body
end
data_class = Class.new do
attr_accessor :title, :body
end
item = data_class.new
item.title = "title"
item.body = "body"
2.times do
assert_equal({title: "title"},
parent.new(item).attributes)
assert_equal({body: "body", title: "title"},
child.new(item).attributes)
end
end
def test_scope_name_method
serializer = Class.new(ActiveModel::Serializer) do
def has_permission?
current_user.super_user?
end
end
user = User.new
user.superuser = true
post = Post.new(title: 'Foo')
a_serializer = serializer.new(post, scope: user, scope_name: :current_user)
assert a_serializer.has_permission?
end
def test_only_option_filters_attributes_and_associations
post = Post.new(title: "New Post", body: "Body of new post")
comments = [Comment.new(title: "Comment1")]
post.comments = comments
post_serializer = PostSerializer.new(post, only: :title)
assert_equal({
post: {
title: "New Post"
}
}, post_serializer.as_json)
end
def test_except_option_filters_attributes_and_associations
post = Post.new(title: "New Post", body: "Body of new post")
comments = [Comment.new(title: "Comment1")]
post.comments = comments
post_serializer = PostSerializer.new(post, except: [:body, :comments])
assert_equal({
post: {
title: "New Post"
}
}, post_serializer.as_json)
end
def test_only_option_takes_precedence_over_custom_defined_include_methods
user = User.new
post = Post.new(title: "New Post", body: "Body of new post", author: "Sausage King")
comments = [Comment.new(title: "Comment")]
post.comments = comments
post_serializer = PostWithMultipleConditionalsSerializer.new(post, scope: user, only: :title)
# comments enabled
post.comments_disabled = false
# superuser - should see author
user.superuser = true
assert_equal({
post: {
title: "New Post"
}
}, post_serializer.as_json)
end
end