Merge pull request #962 from joaomdmoura/render-array-objects

Rendering objects that doesn't have serializers
This commit is contained in:
João Moura 2015-06-26 02:32:04 -03:00
commit 03ac94b9b4
8 changed files with 99 additions and 19 deletions

View File

@ -39,17 +39,18 @@ module ActionController
options.partition { |k, _| ADAPTER_OPTION_KEYS.include? k }.map { |h| Hash[h] }
if use_adapter? && (serializer = get_serializer(resource))
@_serializer_opts[:scope] ||= serialization_scope
@_serializer_opts[:scope_name] = _serialization_scope
# omg hax
object = serializer.new(resource, @_serializer_opts)
adapter = ActiveModel::Serializer::Adapter.create(object, @_adapter_opts)
super(adapter, options)
else
super(resource, options)
begin
serialized = serializer.new(resource, @_serializer_opts)
rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
else
resource = ActiveModel::Serializer::Adapter.create(serialized, @_adapter_opts)
end
end
super(resource, options)
end
end

View File

@ -206,10 +206,16 @@ module ActiveModel
serializer_class = ActiveModel::Serializer.serializer_for(association_value, association_options)
if serializer_class
serializer = serializer_class.new(
association_value,
options.except(:serializer).merge(serializer_from_options(association_options))
)
begin
serializer = serializer_class.new(
association_value,
options.except(:serializer).merge(serializer_from_options(association_options))
)
rescue ActiveModel::Serializer::ArraySerializer::NoSerializerError
virtual_value = association_value
virtual_value = virtual_value.as_json if virtual_value.respond_to?(:as_json)
association_options[:association_options][:virtual_value] = virtual_value
end
elsif !association_value.nil? && !association_value.instance_of?(Object)
association_options[:association_options][:virtual_value] = association_value
end

View File

@ -1,6 +1,7 @@
module ActiveModel
class Serializer
class ArraySerializer
NoSerializerError = Class.new(StandardError)
include Enumerable
delegate :each, to: :@objects
@ -13,7 +14,12 @@ module ActiveModel
:serializer,
ActiveModel::Serializer.serializer_for(object)
)
serializer_class.new(object, options.except(:serializer))
if serializer_class.nil?
fail NoSerializerError, "No serializer found for object: #{object.inspect}"
else
serializer_class.new(object, options.except(:serializer))
end
end
@meta = options[:meta]
@meta_key = options[:meta_key]

View File

@ -47,6 +47,14 @@ module ActionController
render json: @post
end
def render_json_object_without_serializer
render json: {error: 'Result is Invalid'}
end
def render_json_array_object_without_serializer
render json: [{error: 'Result is Invalid'}]
end
def update_and_render_object_with_cache_enabled
@post.updated_at = DateTime.now
@ -160,6 +168,20 @@ module ActionController
assert_equal expected.to_json, @response.body
end
def test_render_json_object_without_serializer
get :render_json_object_without_serializer
assert_equal 'application/json', @response.content_type
assert_equal ({error: 'Result is Invalid'}).to_json, @response.body
end
def test_render_json_array_object_without_serializer
get :render_json_array_object_without_serializer
assert_equal 'application/json', @response.content_type
assert_equal ([{error: 'Result is Invalid'}]).to_json, @response.body
end
def test_render_array_using_implicit_serializer
get :render_array_using_implicit_serializer
assert_equal 'application/json', @response.content_type

View File

@ -8,7 +8,7 @@ module ActiveModel
def setup
ActionController::Base.cache_store.clear
@author = Author.new(id: 1, name: 'Steve K.')
@post = Post.new(title: 'New Post', body: 'Body')
@post = Post.new(id: 42, title: 'New Post', body: 'Body')
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
@post.comments = [@first_comment, @second_comment]
@ -17,20 +17,31 @@ module ActiveModel
@second_comment.post = @post
@blog = Blog.new(id: 1, name: "My Blog!!")
@post.blog = @blog
@serializer = PostSerializer.new(@post)
@adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer)
@tag = Tag.new(id: 1, name: "#hash_tag")
@post.tags = [@tag]
end
def test_has_many
serializer = PostSerializer.new(@post)
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
assert_equal([
{id: 1, body: 'ZOMG A COMMENT'},
{id: 2, body: 'ZOMG ANOTHER COMMENT'}
], @adapter.serializable_hash[:post][:comments])
], adapter.serializable_hash[:post][:comments])
end
def test_has_many_with_no_serializer
serializer = PostWithTagsSerializer.new(@post)
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
assert_equal({
id: 42,
tags: [
{"attributes"=>{"id"=>1, "name"=>"#hash_tag"}}
]
}.to_json, adapter.serializable_hash[:post_with_tags].to_json)
end
end
end
end
end
end

View File

@ -27,7 +27,8 @@ module ActiveModel
@blog.articles = [@post]
@post.blog = @blog
@post_without_comments.blog = nil
@tag = Tag.new(id: 1, name: "#hash_tag")
@post.tags = [@tag]
@serializer = PostSerializer.new(@post)
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer)
end
@ -95,6 +96,7 @@ module ActiveModel
serializer = BlogSerializer.new(@blog)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
actual = adapter.serializable_hash[:data][:relationships][:articles]
expected = {
data: [{
type: "posts",
@ -103,6 +105,21 @@ module ActiveModel
}
assert_equal expected, actual
end
def test_has_many_with_no_serializer
serializer = PostWithTagsSerializer.new(@post)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
assert_equal({
data: {
id: "1",
type: "posts",
relationships: {
tags: { data: nil }
}
}
}, adapter.serializable_hash)
end
end
end
end

View File

@ -76,6 +76,7 @@ Role = Class.new(Model)
User = Class.new(Model)
Location = Class.new(Model)
Place = Class.new(Model)
Tag = Class.new(Model)
Comment = Class.new(Model) do
# Uses a custom non-time-based cache key
def cache_key
@ -224,6 +225,12 @@ PostPreviewSerializer = Class.new(ActiveModel::Serializer) do
belongs_to :author, serializer: AuthorPreviewSerializer
end
PostWithTagsSerializer = Class.new(ActiveModel::Serializer) do
attributes :id
has_many :tags
end
Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do
attributes :id
end

View File

@ -29,8 +29,10 @@ module ActiveModel
@author.roles = []
@blog = Blog.new({ name: 'AMS Blog' })
@post = Post.new({ title: 'New Post', body: 'Body' })
@tag = Tag.new({name: '#hashtagged'})
@comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' })
@post.comments = [@comment]
@post.tags = [@tag]
@post.blog = @blog
@comment.post = @post
@comment.author = nil
@ -65,6 +67,14 @@ module ActiveModel
end
end
def test_has_many_with_no_serializer
PostWithTagsSerializer.new(@post).each_association do |name, serializer, options|
assert_equal name, :tags
assert_equal serializer, nil
assert_equal [{ attributes: { name: "#hashtagged" }}].to_json, options[:virtual_value].to_json
end
end
def test_serializer_options_are_passed_into_associations_serializers
@post_serializer.each_association do |name, association|
if name == :comments