diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 4a5f9668..9f62e615 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -169,7 +169,7 @@ module ActiveModel end def json_key - self.class.root_name + @root || self.class.root_name end def id diff --git a/lib/active_model/serializer/array_serializer.rb b/lib/active_model/serializer/array_serializer.rb index a7e27a56..f2f916e5 100644 --- a/lib/active_model/serializer/array_serializer.rb +++ b/lib/active_model/serializer/array_serializer.rb @@ -5,9 +5,10 @@ module ActiveModel include Enumerable delegate :each, to: :@objects - attr_reader :meta, :meta_key + attr_reader :root, :meta, :meta_key def initialize(objects, options = {}) + @root = options[:root] @resource = objects @objects = objects.map do |object| serializer_class = options.fetch( @@ -26,15 +27,8 @@ module ActiveModel end def json_key - if @objects.first - @objects.first.json_key.pluralize - else - @resource.name.underscore.pluralize if @resource.try(:name) - end - end - - def root=(root) - @objects.first.root = root if @objects.first + key = root || @objects.first.try(:json_key) || @resource.try(:name).try(:underscore) + key.try(:pluralize) end end end diff --git a/test/action_controller/serialization_test.rb b/test/action_controller/serialization_test.rb index 82da8a67..d7e3555e 100644 --- a/test/action_controller/serialization_test.rb +++ b/test/action_controller/serialization_test.rb @@ -18,6 +18,26 @@ module ActionController end end + def render_array_using_custom_root + with_adapter ActiveModel::Serializer::Adapter::Json do + @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) + render json: [@profile], root: "custom_root" + end + end + + def render_array_that_is_empty_using_custom_root + with_adapter ActiveModel::Serializer::Adapter::Json do + render json: [], root: "custom_root" + end + end + + def render_object_using_custom_root + with_adapter ActiveModel::Serializer::Adapter::Json do + @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) + render json: @profile, root: "custom_root" + end + end + def render_array_using_implicit_serializer array = [ Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }), @@ -169,6 +189,30 @@ module ActionController assert_equal expected.to_json, @response.body end + def test_render_array_using_custom_root + get :render_array_using_custom_root + + expected = {custom_roots: [{name: "Name 1", description: "Description 1"}]} + assert_equal 'application/json', @response.content_type + assert_equal expected.to_json, @response.body + end + + def test_render_array_that_is_empty_using_custom_root + get :render_array_that_is_empty_using_custom_root + + expected = {custom_roots: []} + assert_equal 'application/json', @response.content_type + assert_equal expected.to_json, @response.body + end + + def test_render_object_using_custom_root + get :render_object_using_custom_root + + expected = {custom_root: {name: "Name 1", description: "Description 1"}} + assert_equal 'application/json', @response.content_type + assert_equal expected.to_json, @response.body + end + def test_render_json_object_without_serializer get :render_json_object_without_serializer diff --git a/test/array_serializer_test.rb b/test/array_serializer_test.rb index b7ee709c..3eff3ef8 100644 --- a/test/array_serializer_test.rb +++ b/test/array_serializer_test.rb @@ -6,7 +6,13 @@ module ActiveModel def setup @comment = Comment.new @post = Post.new - @serializer = ArraySerializer.new([@comment, @post], {some: :options}) + @resource = build_named_collection @comment, @post + @serializer = ArraySerializer.new(@resource, {some: :options}) + end + + def build_named_collection(*resource) + resource.define_singleton_method(:name){ 'MeResource' } + resource end def test_respond_to_each @@ -39,15 +45,52 @@ module ActiveModel assert_equal @serializer.meta_key, "the meta key" end - def test_json_key_when_resource_is_empty - Array.class_eval do - def name - 'PostComment' - end - end - @post_comments = [] - @serializer = ArraySerializer.new(@post_comments) - assert_equal @serializer.json_key, "post_comments" + def test_root_default + @serializer = ArraySerializer.new([@comment, @post]) + assert_equal @serializer.root, nil + end + + def test_root + expected = 'custom_root' + @serializer = ArraySerializer.new([@comment, @post], root: expected) + assert_equal @serializer.root, expected + end + + def test_root_with_no_serializers + expected = 'custom_root' + @serializer = ArraySerializer.new([], root: expected) + assert_equal @serializer.root, expected + end + + def test_json_key + assert_equal @serializer.json_key, 'comments' + end + + def test_json_key_with_resource_with_name_and_no_serializers + serializer = ArraySerializer.new(build_named_collection) + assert_equal serializer.json_key, 'me_resources' + end + + def test_json_key_with_resource_with_nil_name_and_no_serializers + resource = [] + resource.define_singleton_method(:name){ nil } + serializer = ArraySerializer.new(resource) + assert_equal serializer.json_key, nil + end + + def test_json_key_with_resource_without_name_and_no_serializers + serializer = ArraySerializer.new([]) + assert_equal serializer.json_key, nil + end + + def test_json_key_with_root + serializer = ArraySerializer.new(@resource, root: 'custom_root') + assert_equal serializer.json_key, 'custom_roots' + end + + def test_json_key_with_root_and_no_serializers + serializer = ArraySerializer.new(build_named_collection, root: 'custom_root') + assert_equal serializer.json_key, 'custom_roots' end end end diff --git a/test/serializers/root_test.rb b/test/serializers/root_test.rb new file mode 100644 index 00000000..05853e39 --- /dev/null +++ b/test/serializers/root_test.rb @@ -0,0 +1,19 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class RootTest < Minitest::Test + + def setup + @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) + @profile_serializer = ProfileSerializer.new(@post, {root: 'smth'}) + end + + def test_overwrite_root + setup + assert_equal('smth', @profile_serializer.json_key) + end + + end + end +end