From e8573e527f1b9466b7d62ea69465a3b8f80f7238 Mon Sep 17 00:00:00 2001 From: James MacAulay Date: Fri, 9 Apr 2010 12:29:28 -0400 Subject: [PATCH] add :root option to ActiveModel JSON serialization --- activemodel/lib/active_model/serializers/json.rb | 23 ++++++++++++++++++- .../serializeration/json_serialization_test.rb | 23 +++++++++++++++++++- activerecord/test/cases/json_serialization_test.rb | 20 +++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb index 794de7d..bfb83e7 100644 --- a/activemodel/lib/active_model/serializers/json.rb +++ b/activemodel/lib/active_model/serializers/json.rb @@ -30,6 +30,19 @@ module ActiveModel # # => {"id": 1, "name": "Konata Izumi", "age": 16, # "created_at": "2006/08/01", "awesome": true} # + # The include_root_in_json setting can be overridden with the :root + # option to specify an arbitrary string as the top-level key, or to cancel the use of + # a root at all: + # + # konata.to_json(:root => "person") + # # => { "person": {"id": 1, "name": "Konata Izumi", "age": 16, + # "created_at": "2006/08/01", "awesome": true} } + # + # ActiveRecord::Base.include_root_in_json = true + # konata.to_json(:root => false) + # # => {"id": 1, "name": "Konata Izumi", "age": 16, + # "created_at": "2006/08/01", "awesome": true} + # # The remainder of the examples in this section assume include_root_in_json is set to # false. # @@ -78,8 +91,14 @@ module ActiveModel # {"comments": [{"body": "Don't think too hard"}], # "title": "So I was thinking"}]} def encode_json(encoder) - hash = serializable_hash(encoder.options) - hash = { self.class.model_name.element => hash } if include_root_in_json + opts = encoder.options + hash = serializable_hash(opts) + root = if opts && opts.key?(:root) + opts[:root].to_s + elsif include_root_in_json + self.class.model_name.element + end + hash = { root => hash } if root ActiveSupport::JSON.encode(hash) end diff --git a/activemodel/test/cases/serializeration/json_serialization_test.rb b/activemodel/test/cases/serializeration/json_serialization_test.rb index 81df52f..cb031c4 100644 --- a/activemodel/test/cases/serializeration/json_serialization_test.rb +++ b/activemodel/test/cases/serializeration/json_serialization_test.rb @@ -21,7 +21,8 @@ class JsonSerializationTest < ActiveModel::TestCase @contact.preferences = { 'shows' => 'anime' } end - test "should include root in json" do + test "should include root in json from class setting" do + assert_no_match %r{^\{"[^"]*":\{}, @contact.to_json begin Contact.include_root_in_json = true json = @contact.to_json @@ -37,6 +38,26 @@ class JsonSerializationTest < ActiveModel::TestCase end end + test "should include root in json from option" do + assert_no_match %r{^\{"[^"]*":\{}, @contact.to_json + assert_match %r{^\{"person":\{}, @contact.to_json(:root => 'person') + begin + Contact.include_root_in_json = true + assert_match %r{^\{"person":\{}, @contact.to_json(:root => 'person') + ensure + Contact.include_root_in_json = false + end + end + + test "should not include root when option overrides class setting" do + begin + Contact.include_root_in_json = true + assert_no_match %r{^\{"[^"]*":\{}, @contact.to_json(:root => false) + ensure + Contact.include_root_in_json = false + end + end + test "should encode all encodable attributes" do json = @contact.to_json diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb index a3145d2..3e7c935 100644 --- a/activerecord/test/cases/json_serialization_test.rb +++ b/activerecord/test/cases/json_serialization_test.rb @@ -44,6 +44,26 @@ class JsonSerializationTest < ActiveRecord::TestCase ensure Contact.include_root_in_json = false end + + def test_should_include_root_in_json_from_option + assert_no_match %r{^\{"[^"]*":\{}, @contact.to_json + assert_match %r{^\{"person":\{}, @contact.to_json(:root => 'person') + begin + Contact.include_root_in_json = true + assert_match %r{^\{"person":\{}, @contact.to_json(:root => 'person') + ensure + Contact.include_root_in_json = false + end + end + + def test_should_not_include_root_when_option_overrides_class_setting + begin + Contact.include_root_in_json = true + assert_no_match %r{^\{"[^"]*":\{}, @contact.to_json(:root => false) + ensure + Contact.include_root_in_json = false + end + end def test_should_encode_all_encodable_attributes json = @contact.to_json -- 1.6.5.3