diff --git a/lib/action_controller/serialization.rb b/lib/action_controller/serialization.rb index e47248d4..f26f0112 100644 --- a/lib/action_controller/serialization.rb +++ b/lib/action_controller/serialization.rb @@ -12,7 +12,7 @@ module ActionController if serializer # omg hax - object = serializer.new(resource) + object = serializer.new(resource, options) adapter = ActiveModel::Serializer.adapter.new(object) super(adapter, options) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 05a79900..ccb060a1 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -73,12 +73,12 @@ module ActiveModel def self.adapter adapter_class = case config.adapter - when Symbol - class_name = "ActiveModel::Serializer::Adapter::#{config.adapter.to_s.classify}" - class_name.safe_constantize - when Class - config.adapter - end + when Symbol + class_name = "ActiveModel::Serializer::Adapter::#{config.adapter.to_s.classify}" + class_name.safe_constantize + when Class + config.adapter + end unless adapter_class valid_adapters = Adapter.constants.map { |klass| ":#{klass.to_s.downcase}" } raise ArgumentError, "Unknown adapter: #{config.adapter}. Valid adapters are: #{valid_adapters}" @@ -87,10 +87,31 @@ module ActiveModel adapter_class end - attr_accessor :object + def self._root + @@root ||= false + end - def initialize(object) + def self._root=(root) + @@root = root + end + + def self.root_name + name.demodulize.underscore.sub(/_serializer$/, '') if name + end + + attr_accessor :object, :root + + def initialize(object, options = {}) @object = object + @root = options[:root] || (self.class._root ? self.class.root_name : false) + end + + def json_key + if root == true || root.nil? + self.class.root_name + else + root + end end def attributes(options = {}) diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index 2fae98ff..8eacc39a 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -8,7 +8,7 @@ module ActiveModel attr_reader :serializer - def initialize(serializer) + def initialize(serializer, options = {}) @serializer = serializer end @@ -16,8 +16,14 @@ module ActiveModel raise NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.' end - def to_json(options={}) - serializable_hash(options).to_json + def to_json(options = {}) + result = serializable_hash(options) + + if root = options.fetch(:root, serializer.json_key) + result = { root => result } + end + + result.to_json end end end diff --git a/lib/active_model/serializer/adapter/json.rb b/lib/active_model/serializer/adapter/json.rb index f37fc8d4..82bc319e 100644 --- a/lib/active_model/serializer/adapter/json.rb +++ b/lib/active_model/serializer/adapter/json.rb @@ -13,6 +13,7 @@ module ActiveModel @hash[name] = association.attributes(options) end end + @hash end end diff --git a/test/action_controller/serialization_test.rb b/test/action_controller/serialization_test.rb index c4ee3497..085ed687 100644 --- a/test/action_controller/serialization_test.rb +++ b/test/action_controller/serialization_test.rb @@ -5,7 +5,13 @@ module ActionController class ImplicitSerializerTest < ActionController::TestCase class MyController < ActionController::Base def render_using_implicit_serializer - render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) + @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) + render json: @profile + end + + def render_using_custom_root + @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) + render json: @profile, root: "custom_root" end end @@ -18,8 +24,13 @@ module ActionController assert_equal 'application/json', @response.content_type assert_equal '{"name":"Name 1","description":"Description 1"}', @response.body 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 end end end - -