diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 0c2f3860..615c9704 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -5,7 +5,16 @@ module ActiveModel base._attributes = {} end - attr_accessor :_attributes + attr_accessor :_root, :_attributes + + def root(root) + @_root = root + end + alias root= root + + def root_name + name.demodulize.underscore.sub(/_serializer$/, '') if name + end def attributes(*attrs) @_attributes = attrs.map(&:to_s) @@ -18,10 +27,12 @@ module ActiveModel end end - def initialize(object) + def initialize(object, options={}) @object = object + @root = options[:root] || self.class._root + @root = self.class.root_name if @root == true end - attr_accessor :object + attr_accessor :object, :root alias read_attribute_for_serialization send @@ -37,7 +48,11 @@ module ActiveModel end def as_json(options={}) - serializable_hash + if root = options[:root] || self.root + { root.to_s => serializable_hash } + else + serializable_hash + end end end end diff --git a/test/serializer/root_test.rb b/test/serializer/root_test.rb new file mode 100644 index 00000000..74a3cc37 --- /dev/null +++ b/test/serializer/root_test.rb @@ -0,0 +1,103 @@ +require 'newbase/test_helper' +require 'newbase/active_model/serializer' + +module SerializerTest + module Root + class Model + def initialize(hash={}) + @attributes = hash + end + + def read_attribute_for_serialization(name) + @attributes[name] + end + end + + class RootAsOptionTest < ActiveModel::TestCase + class ModelSerializer < ActiveModel::Serializer + attributes :attr1, :attr2 + end + ModelSerializer.root = true + + def setup + @model = Model.new({ :attr1 => 'value1', :attr2 => 'value2', :attr3 => 'value3' }) + @serializer = ModelSerializer.new(@model, root: 'initialize') + end + + def test_root_is_not_displayed_using_serializable_hash + assert_equal({ + 'attr1' => 'value1', 'attr2' => 'value2' + }, @serializer.serializable_hash) + end + + def test_root_using_as_json + assert_equal({ + 'initialize' => { + 'attr1' => 'value1', 'attr2' => 'value2' + } + }, @serializer.as_json) + end + + def test_root_from_serializer_name + @serializer = ModelSerializer.new(@model) + + assert_equal({ + 'model' => { + 'attr1' => 'value1', 'attr2' => 'value2' + } + }, @serializer.as_json) + end + + def test_root_as_argument_takes_presedence + assert_equal({ + 'argument' => { + 'attr1' => 'value1', 'attr2' => 'value2' + } + }, @serializer.as_json(root: 'argument')) + end + end + + class RootInSerializerTest < ActiveModel::TestCase + class ModelSerializer < ActiveModel::Serializer + root :in_serializer + attributes :attr1, :attr2 + end + + def setup + model = Model.new({ :attr1 => 'value1', :attr2 => 'value2', :attr3 => 'value3' }) + @serializer = ModelSerializer.new(model) + @rooted_serializer = ModelSerializer.new(model, root: :initialize) + end + + def test_root_is_not_displayed_using_serializable_hash + assert_equal({ + 'attr1' => 'value1', 'attr2' => 'value2' + }, @serializer.serializable_hash) + end + + def test_root_using_as_json + assert_equal({ + 'in_serializer' => { + 'attr1' => 'value1', 'attr2' => 'value2' + } + }, @serializer.as_json) + end + + def test_root_in_initializer_takes_precedence + assert_equal({ + 'initialize' => { + 'attr1' => 'value1', 'attr2' => 'value2' + } + }, @rooted_serializer.as_json) + end + + def test_root_as_argument_takes_precedence + assert_equal({ + 'argument' => { + 'attr1' => 'value1', 'attr2' => 'value2' + } + }, @rooted_serializer.as_json(root: :argument)) + end + end + end +end