Merge pull request #958 from joaomdmoura/spliting-json-adapter

Splitting json adapter into two
This commit is contained in:
João Moura 2015-06-16 11:54:33 -03:00
commit bc8fd0a44a
23 changed files with 81 additions and 109 deletions

View File

@ -6,7 +6,7 @@ module ActionController
include ActionController::Renderers include ActionController::Renderers
ADAPTER_OPTION_KEYS = [:include, :fields, :root, :adapter] ADAPTER_OPTION_KEYS = [:include, :fields, :adapter]
included do included do
class_attribute :_serialization_scope class_attribute :_serialization_scope

View File

@ -145,14 +145,6 @@ module ActiveModel
adapter_class adapter_class
end end
def self._root
@@root ||= false
end
def self._root=(root)
@@root = root
end
def self.root_name def self.root_name
name.demodulize.underscore.sub(/_serializer$/, '') if name name.demodulize.underscore.sub(/_serializer$/, '') if name
end end
@ -162,7 +154,7 @@ module ActiveModel
def initialize(object, options = {}) def initialize(object, options = {})
@object = object @object = object
@options = options @options = options
@root = options[:root] || (self.class._root ? self.class.root_name : false) @root = options[:root]
@meta = options[:meta] @meta = options[:meta]
@meta_key = options[:meta_key] @meta_key = options[:meta_key]
@scope = options[:scope] @scope = options[:scope]
@ -176,11 +168,7 @@ module ActiveModel
end end
def json_key def json_key
if root == true || root.nil? self.class.root_name
self.class.root_name
else
root
end
end end
def id def id

View File

@ -5,6 +5,7 @@ module ActiveModel
class Adapter class Adapter
extend ActiveSupport::Autoload extend ActiveSupport::Autoload
autoload :Json autoload :Json
autoload :FlattenJson
autoload :Null autoload :Null
autoload :JsonApi autoload :JsonApi
@ -21,7 +22,8 @@ module ActiveModel
def as_json(options = {}) def as_json(options = {})
hash = serializable_hash(options) hash = serializable_hash(options)
include_meta(hash) include_meta(hash) unless self.class == FlattenJson
hash
end end
def self.create(resource, options = {}) def self.create(resource, options = {})
@ -48,7 +50,7 @@ module ActiveModel
yield yield
end end
elsif is_fragment_cached? elsif is_fragment_cached?
FragmentCache.new(self, @cached_serializer, @options, @root).fetch FragmentCache.new(self, @cached_serializer, @options).fetch
else else
yield yield
end end
@ -82,11 +84,11 @@ module ActiveModel
end end
def root def root
@options.fetch(:root) { serializer.json_key } serializer.json_key.to_sym if serializer.json_key
end end
def include_meta(json) def include_meta(json)
json[meta_key] = meta if meta && root json[meta_key] = meta if meta
json json
end end
end end

View File

@ -0,0 +1,12 @@
module ActiveModel
class Serializer
class Adapter
class FlattenJson < Json
def serializable_hash(options = {})
super
@result
end
end
end
end
end

View File

@ -5,8 +5,7 @@ module ActiveModel
attr_reader :serializer attr_reader :serializer
def initialize(adapter, serializer, options, root) def initialize(adapter, serializer, options)
@root = root
@options = options @options = options
@adapter = adapter @adapter = adapter
@serializer = serializer @serializer = serializer

View File

@ -6,7 +6,7 @@ module ActiveModel
class Json < Adapter class Json < Adapter
def serializable_hash(options = {}) def serializable_hash(options = {})
if serializer.respond_to?(:each) if serializer.respond_to?(:each)
@result = serializer.map{|s| self.class.new(s).serializable_hash } @result = serializer.map{|s| FlattenJson.new(s).serializable_hash }
else else
@hash = {} @hash = {}
@ -37,16 +37,13 @@ module ActiveModel
@result = @core.merge @hash @result = @core.merge @hash
end end
if root { root => @result }
@result = { root => @result } end
else
@result def fragment_cache(cached_hash, non_cached_hash)
end Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash)
end end
end
def fragment_cache(cached_hash, non_cached_hash)
Json::FragmentCache.new().fragment_cache(cached_hash, non_cached_hash)
end end
end end
end end

View File

@ -6,7 +6,6 @@ module ActiveModel
class JsonApi < Adapter class JsonApi < Adapter
def initialize(serializer, options = {}) def initialize(serializer, options = {})
super super
serializer.root = true
@hash = { data: [] } @hash = { data: [] }
if fields = options.delete(:fields) if fields = options.delete(:fields)

View File

@ -7,9 +7,8 @@ module ActiveModel
attr_reader :meta, :meta_key attr_reader :meta, :meta_key
def initialize(objects, options = {}) def initialize(objects, options = {})
options.merge!(root: nil) @resource = objects
@objects = objects.map do |object|
@objects = objects.map do |object|
serializer_class = options.fetch( serializer_class = options.fetch(
:serializer, :serializer,
ActiveModel::Serializer.serializer_for(object) ActiveModel::Serializer.serializer_for(object)
@ -21,7 +20,11 @@ module ActiveModel
end end
def json_key def json_key
@objects.first.json_key if @objects.first if @objects.first
@objects.first.json_key.pluralize
else
@resource.name.downcase.pluralize if @resource.try(:name)
end
end end
def root=(root) def root=(root)

View File

@ -6,7 +6,7 @@ module ActiveModel
included do |base| included do |base|
base.config.array_serializer = ActiveModel::Serializer::ArraySerializer base.config.array_serializer = ActiveModel::Serializer::ArraySerializer
base.config.adapter = :json base.config.adapter = :flatten_json
end end
end end
end end

View File

@ -12,8 +12,8 @@ module ActiveModel
end end
def fields_for(serializer) def fields_for(serializer)
key = serializer.json_key || serializer.class.root_name key = serializer.json_key
fields[key.to_sym] fields[key.to_sym] || fields[key.pluralize.to_sym]
end end
private private

View File

@ -77,12 +77,10 @@ module ActionController
get :render_array_using_explicit_serializer get :render_array_using_explicit_serializer
assert_equal 'application/json', @response.content_type assert_equal 'application/json', @response.content_type
expected = { expected = [
'paginated' => [ { 'name' => 'Name 1' },
{ 'name' => 'Name 1' }, { 'name' => 'Name 2' }
{ 'name' => 'Name 2' } ]
]
}
assert_equal expected.to_json, @response.body assert_equal expected.to_json, @response.body
end end

View File

@ -10,13 +10,17 @@ module ActionController
end end
def render_using_custom_root def render_using_custom_root
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) with_adapter ActiveModel::Serializer::Adapter::Json do
render json: @profile, root: "custom_root" @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
render json: @profile, root: "custom_root"
end
end end
def render_using_custom_root_and_meta def render_using_custom_root_and_meta
@profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) with_adapter ActiveModel::Serializer::Adapter::Json do
render json: @profile, root: "custom_root", meta: { total: 10 } @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
render json: @profile, root: "custom_root", meta: { total: 10 }
end
end end
def render_using_default_adapter_root def render_using_default_adapter_root
@ -34,11 +38,13 @@ module ActionController
end end
def render_array_using_custom_root_and_meta def render_array_using_custom_root_and_meta
array = [ with_adapter ActiveModel::Serializer::Adapter::Json do
Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }), array = [
Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' }) Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
] Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })
render json: array, root: "custom_root", meta: { total: 10 } ]
render json: array, root: "custom_root", meta: { total: 10 }
end
end end
def render_array_using_implicit_serializer def render_array_using_implicit_serializer
@ -167,20 +173,6 @@ module ActionController
assert_equal expected.to_json, @response.body assert_equal expected.to_json, @response.body
end end
def test_render_using_custom_root
get :render_using_custom_root
assert_equal 'application/json', @response.content_type
assert_equal '{"custom_root":{"name":"Name 1","description":"Description 1"}}', @response.body
end
def test_render_using_custom_root_and_meta
get :render_using_custom_root_and_meta
assert_equal 'application/json', @response.content_type
assert_equal '{"custom_root":{"name":"Name 1","description":"Description 1"},"meta":{"total":10}}', @response.body
end
def test_render_using_default_root def test_render_using_default_root
get :render_using_default_adapter_root get :render_using_default_adapter_root
@ -217,25 +209,6 @@ module ActionController
assert_equal expected.to_json, @response.body assert_equal expected.to_json, @response.body
end end
def test_render_array_using_custom_root_and_meta
get :render_array_using_custom_root_and_meta
assert_equal 'application/json', @response.content_type
expected = { custom_root: [
{
name: 'Name 1',
description: 'Description 1',
},
{
name: 'Name 2',
description: 'Description 2',
}],
meta: { total: 10 }
}
assert_equal expected.to_json, @response.body
end
def test_render_array_using_implicit_serializer def test_render_array_using_implicit_serializer
get :render_array_using_implicit_serializer get :render_array_using_implicit_serializer
assert_equal 'application/json', @response.content_type assert_equal 'application/json', @response.content_type

View File

@ -8,7 +8,7 @@ module ActiveModel
@role = Role.new(name: 'Great Author', description:nil) @role = Role.new(name: 'Great Author', description:nil)
@role.author = [@author] @role.author = [@author]
@role_serializer = RoleSerializer.new(@role) @role_serializer = RoleSerializer.new(@role)
@role_hash = FragmentCache.new(RoleSerializer.adapter.new(@role_serializer), @role_serializer, {}, nil) @role_hash = FragmentCache.new(RoleSerializer.adapter.new(@role_serializer), @role_serializer, {})
end end
def test_fragment_fetch_with_virtual_attributes def test_fragment_fetch_with_virtual_attributes

View File

@ -25,21 +25,21 @@ module ActiveModel
end end
def test_includes_post def test_includes_post
assert_equal({id: 42, title: 'New Post', body: 'Body'}, @adapter.serializable_hash[:post]) assert_equal({id: 42, title: 'New Post', body: 'Body'}, @adapter.serializable_hash[:comment][:post])
end end
def test_include_nil_author def test_include_nil_author
serializer = PostSerializer.new(@anonymous_post) serializer = PostSerializer.new(@anonymous_post)
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer) adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
assert_equal({title: "Hello!!", body: "Hello, world!!", id: 43, comments: [], blog: {id: 999, name: "Custom blog"}, author: nil}, adapter.serializable_hash) assert_equal({post: {title: "Hello!!", body: "Hello, world!!", id: 43, comments: [], blog: {id: 999, name: "Custom blog"}, author: nil}}, adapter.serializable_hash)
end end
def test_include_nil_author_with_specified_serializer def test_include_nil_author_with_specified_serializer
serializer = PostPreviewSerializer.new(@anonymous_post) serializer = PostPreviewSerializer.new(@anonymous_post)
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer) adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
assert_equal({title: "Hello!!", body: "Hello, world!!", id: 43, comments: [], author: nil}, adapter.serializable_hash) assert_equal({posts: {title: "Hello!!", body: "Hello, world!!", id: 43, comments: [], author: nil}}, adapter.serializable_hash)
end end
end end
end end

View File

@ -28,16 +28,16 @@ module ActiveModel
@serializer = ArraySerializer.new([@blog], serializer: CustomBlogSerializer) @serializer = ArraySerializer.new([@blog], serializer: CustomBlogSerializer)
@adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer) @adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer)
expected = [{ expected = {custom_blogs:[{
id: 1, id: 1,
special_attribute: "Special", special_attribute: "Special",
articles: [{id: 1,title: "Hello!!", body: "Hello, world!!"}, {id: 2, title: "New Post", body: "Body"}] articles: [{id: 1,title: "Hello!!", body: "Hello, world!!"}, {id: 2, title: "New Post", body: "Body"}]
}] }]}
assert_equal expected, @adapter.serializable_hash assert_equal expected, @adapter.serializable_hash
end end
def test_include_multiple_posts def test_include_multiple_posts
expected = [{ expected = { posts: [{
title: "Hello!!", title: "Hello!!",
body: "Hello, world!!", body: "Hello, world!!",
id: 1, id: 1,
@ -63,7 +63,7 @@ module ActiveModel
id: 999, id: 999,
name: "Custom blog" name: "Custom blog"
} }
}] }]}
assert_equal expected, @adapter.serializable_hash assert_equal expected, @adapter.serializable_hash
end end
end end

View File

@ -26,7 +26,7 @@ module ActiveModel
assert_equal([ assert_equal([
{id: 1, body: 'ZOMG A COMMENT'}, {id: 1, body: 'ZOMG A COMMENT'},
{id: 2, body: 'ZOMG ANOTHER COMMENT'} {id: 2, body: 'ZOMG ANOTHER COMMENT'}
], @adapter.serializable_hash[:comments]) ], @adapter.serializable_hash[:post][:comments])
end end
end end
end end

View File

@ -86,7 +86,6 @@ module ActiveModel
} }
} }
] ]
assert_equal(expected, @adapter.serializable_hash[:data]) assert_equal(expected, @adapter.serializable_hash[:data])
end end

View File

@ -25,7 +25,7 @@ module ActiveModel
assert_equal([ assert_equal([
{id: 1, body: 'ZOMG A COMMENT'}, {id: 1, body: 'ZOMG A COMMENT'},
{id: 2, body: 'ZOMG ANOTHER COMMENT'} {id: 2, body: 'ZOMG ANOTHER COMMENT'}
], @adapter.serializable_hash[:comments]) ], @adapter.serializable_hash[:post][:comments])
end end
end end
end end

View File

@ -31,7 +31,7 @@ module ActiveModel
def test_create_adapter def test_create_adapter
adapter = ActiveModel::Serializer::Adapter.create(@serializer) adapter = ActiveModel::Serializer::Adapter.create(@serializer)
assert_equal ActiveModel::Serializer::Adapter::Json, adapter.class assert_equal ActiveModel::Serializer::Adapter::FlattenJson, adapter.class
end end
def test_create_adapter_with_override def test_create_adapter_with_override

View File

@ -11,7 +11,7 @@ module ActiveModel
def test_returns_default_adapter def test_returns_default_adapter
adapter = ActiveModel::Serializer.adapter adapter = ActiveModel::Serializer.adapter
assert_equal ActiveModel::Serializer::Adapter::Json, adapter assert_equal ActiveModel::Serializer::Adapter::FlattenJson, adapter
end end
def test_overwrite_adapter_with_symbol def test_overwrite_adapter_with_symbol

View File

@ -15,13 +15,13 @@ module ActiveModel
def test_json_serializable_hash def test_json_serializable_hash
adapter = ActiveModel::Serializer::Adapter::Json.new(@blog_serializer) adapter = ActiveModel::Serializer::Adapter::Json.new(@blog_serializer)
assert_equal({:id=>1, :title=>"AMS Hints"}, adapter.serializable_hash) assert_equal({alternate_blog: { id:1, title:"AMS Hints"}}, adapter.serializable_hash)
end end
def test_attribute_inheritance_with_key def test_attribute_inheritance_with_key
inherited_klass = Class.new(AlternateBlogSerializer) inherited_klass = Class.new(AlternateBlogSerializer)
blog_serializer = inherited_klass.new(@blog) blog_serializer = inherited_klass.new(@blog)
adapter = ActiveModel::Serializer::Adapter::Json.new(blog_serializer) adapter = ActiveModel::Serializer::Adapter::FlattenJson.new(blog_serializer)
assert_equal({:id=>1, :title=>"AMS Hints"}, adapter.serializable_hash) assert_equal({:id=>1, :title=>"AMS Hints"}, adapter.serializable_hash)
end end

View File

@ -8,7 +8,7 @@ module ActiveModel
end end
def test_default_adapter def test_default_adapter
assert_equal :json, ActiveModel::Serializer.config.adapter assert_equal :flatten_json, ActiveModel::Serializer.config.adapter
end end
end end
end end

View File

@ -12,9 +12,10 @@ module ActiveModel
end end
def test_meta_is_present_with_root def test_meta_is_present_with_root
adapter = load_adapter(root: "blog", meta: {total: 10}) serializer = AlternateBlogSerializer.new(@blog, meta: {total: 10})
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer, root: 'blog')
expected = { expected = {
"blog" => { alternate_blog: {
id: 1, id: 1,
title: "AMS Hints" title: "AMS Hints"
}, },
@ -35,9 +36,10 @@ module ActiveModel
end end
def test_meta_key_is_used def test_meta_key_is_used
adapter = load_adapter(root: "blog", meta: {total: 10}, meta_key: "haha_meta") serializer = AlternateBlogSerializer.new(@blog, root: 'blog', meta: {total: 10}, meta_key: "haha_meta")
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer, root: 'blog')
expected = { expected = {
"blog" => { alternate_blog: {
id: 1, id: 1,
title: "AMS Hints" title: "AMS Hints"
}, },
@ -50,7 +52,7 @@ module ActiveModel
def test_meta_is_not_present_on_arrays_without_root def test_meta_is_not_present_on_arrays_without_root
serializer = ArraySerializer.new([@blog], meta: {total: 10}) serializer = ArraySerializer.new([@blog], meta: {total: 10})
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer) adapter = ActiveModel::Serializer::Adapter::FlattenJson.new(serializer)
expected = [{ expected = [{
id: 1, id: 1,
name: "AMS Hints", name: "AMS Hints",
@ -71,7 +73,7 @@ module ActiveModel
serializer = ArraySerializer.new([@blog], meta: {total: 10}, meta_key: "haha_meta") serializer = ArraySerializer.new([@blog], meta: {total: 10}, meta_key: "haha_meta")
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer, root: 'blog') adapter = ActiveModel::Serializer::Adapter::Json.new(serializer, root: 'blog')
expected = { expected = {
'blog' => [{ blogs: [{
id: 1, id: 1,
name: "AMS Hints", name: "AMS Hints",
writer: { writer: {
@ -98,7 +100,7 @@ module ActiveModel
options.partition { |k, _| ActionController::Serialization::ADAPTER_OPTION_KEYS.include? k }.map { |h| Hash[h] } options.partition { |k, _| ActionController::Serialization::ADAPTER_OPTION_KEYS.include? k }.map { |h| Hash[h] }
serializer = AlternateBlogSerializer.new(@blog, serializer_opts) serializer = AlternateBlogSerializer.new(@blog, serializer_opts)
ActiveModel::Serializer::Adapter::Json.new(serializer, adapter_opts) ActiveModel::Serializer::Adapter::FlattenJson.new(serializer, adapter_opts)
end end
end end
end end