From ca41901fb8acd35f74fe68b7251cc1f22d4d0087 Mon Sep 17 00:00:00 2001 From: Benedikt Deicke Date: Thu, 21 May 2015 16:23:01 +0200 Subject: [PATCH] Adjusts JsonApi adapter to serialize attributes in a nested `attributes` hash --- .../serializer/adapter/json_api.rb | 33 +++++---- .../adapter/json_api/fragment_cache.rb | 5 +- .../adapter_selector_test.rb | 8 ++- .../action_controller/json_api_linked_test.rb | 24 ++++--- .../serialization_scope_name_test.rb | 4 +- test/action_controller/serialization_test.rb | 24 ++++--- test/adapter/json_api/belongs_to_test.rb | 26 ++++--- test/adapter/json_api/collection_test.rb | 20 ++++-- test/adapter/json_api/has_many_test.rb | 8 ++- test/adapter/json_api/has_one_test.rb | 6 +- test/adapter/json_api/linked_test.rb | 68 +++++++++++++------ 11 files changed, 148 insertions(+), 78 deletions(-) diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 6cc69549..f8bea380 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -85,26 +85,31 @@ module ActiveModel if serializer.respond_to?(:each) result = [] serializer.each do |object| - options[:fields] = @fieldset && @fieldset.fields_for(serializer) - result << cache_check(object) do - options[:required_fields] = [:id, :type] - attributes = object.attributes(options) - attributes[:id] = attributes[:id].to_s - result << attributes - end + result << resource_object_for(object, options) end else - options[:fields] = @fieldset && @fieldset.fields_for(serializer) - options[:required_fields] = [:id, :type] - result = cache_check(serializer) do - result = serializer.attributes(options) - result[:id] = result[:id].to_s - result - end + result = resource_object_for(serializer, options) end result end + def resource_object_for(serializer, options) + options[:fields] = @fieldset && @fieldset.fields_for(serializer) + options[:required_fields] = [:id, :type] + + cache_check(serializer) do + attributes = serializer.attributes(options) + + result = { + id: attributes.delete(:id).to_s, + type: attributes.delete(:type) + } + + result[:attributes] = attributes if attributes.any? + result + end + end + def include_assoc?(assoc) return false unless @options[:include] check_assoc("#{assoc}$") diff --git a/lib/active_model/serializer/adapter/json_api/fragment_cache.rb b/lib/active_model/serializer/adapter/json_api/fragment_cache.rb index 75630b61..6ce1c184 100644 --- a/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +++ b/lib/active_model/serializer/adapter/json_api/fragment_cache.rb @@ -10,9 +10,10 @@ module ActiveModel core_non_cached = non_cached_hash.first no_root_cache = cached_hash.delete_if {|key, value| key == core_cached[0] } no_root_non_cache = non_cached_hash.delete_if {|key, value| key == core_non_cached[0] } - cached_resource = (core_cached[1]) ? core_cached[1].merge(core_non_cached[1]) : core_non_cached[1] + cached_resource = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1] hash = (root) ? { root => cached_resource } : cached_resource - hash.merge no_root_non_cache.merge no_root_cache + + hash.deep_merge no_root_non_cache.deep_merge no_root_cache end end diff --git a/test/action_controller/adapter_selector_test.rb b/test/action_controller/adapter_selector_test.rb index 07bdf0a7..1ff03cf2 100644 --- a/test/action_controller/adapter_selector_test.rb +++ b/test/action_controller/adapter_selector_test.rb @@ -32,10 +32,12 @@ module ActionController expected = { data: { - name: "Name 1", - description: "Description 1", id: assigns(:profile).id.to_s, - type: "profiles" + type: "profiles", + attributes: { + name: "Name 1", + description: "Description 1", + } } } diff --git a/test/action_controller/json_api_linked_test.rb b/test/action_controller/json_api_linked_test.rb index d3a1f844..387640bc 100644 --- a/test/action_controller/json_api_linked_test.rb +++ b/test/action_controller/json_api_linked_test.rb @@ -91,7 +91,7 @@ module ActionController response = JSON.parse(@response.body) assert response.key? 'included' assert_equal 1, response['included'].size - assert_equal 'Steve K.', response['included'].first['name'] + assert_equal 'Steve K.', response['included'].first['attributes']['name'] end def test_render_resource_with_nested_has_many_include @@ -101,7 +101,9 @@ module ActionController { "id" => "1", "type" => "authors", - "name" => "Steve K.", + "attributes" => { + "name" => "Steve K." + }, "links" => { "posts" => { "linkage" => [] }, "roles" => { "linkage" => [{ "type" =>"roles", "id" => "1" }, { "type" =>"roles", "id" => "2" }] }, @@ -110,18 +112,22 @@ module ActionController }, { "id" => "1", "type" => "roles", - "name" => "admin", - "description" => nil, - "slug" => "admin-1", + "attributes" => { + "name" => "admin", + "description" => nil, + "slug" => "admin-1" + }, "links" => { "author" => { "linkage" => { "type" =>"authors", "id" => "1" } } } }, { "id" => "2", "type" => "roles", - "name" => "colab", - "description" => nil, - "slug" => "colab-2", + "attributes" => { + "name" => "colab", + "description" => nil, + "slug" => "colab-2" + }, "links" => { "author" => { "linkage" => { "type" =>"authors", "id" => "1" } } } @@ -135,7 +141,7 @@ module ActionController response = JSON.parse(@response.body) assert response.key? 'included' assert_equal 1, response['included'].size - assert_equal 'Anonymous', response['included'].first['name'] + assert_equal 'Anonymous', response['included'].first['attributes']['name'] end def test_render_collection_without_include diff --git a/test/action_controller/serialization_scope_name_test.rb b/test/action_controller/serialization_scope_name_test.rb index 7a406e7a..2af0a1fa 100644 --- a/test/action_controller/serialization_scope_name_test.rb +++ b/test/action_controller/serialization_scope_name_test.rb @@ -27,7 +27,7 @@ class DefaultScopeNameTest < ActionController::TestCase def test_default_scope_name get :render_new_user - assert_equal '{"data":{"admin?":false,"id":"1","type":"users"}}', @response.body + assert_equal '{"data":{"id":"1","type":"users","attributes":{"admin?":false}}}', @response.body end end @@ -58,6 +58,6 @@ class SerializationScopeNameTest < ActionController::TestCase def test_override_scope_name_with_controller get :render_new_user - assert_equal '{"data":{"admin?":true,"id":"1","type":"users"}}', @response.body + assert_equal '{"data":{"id":"1","type":"users","attributes":{"admin?":true}}}', @response.body end end \ No newline at end of file diff --git a/test/action_controller/serialization_test.rb b/test/action_controller/serialization_test.rb index ff84655c..ad20bc3e 100644 --- a/test/action_controller/serialization_test.rb +++ b/test/action_controller/serialization_test.rb @@ -166,10 +166,12 @@ module ActionController expected = { data: { - name: "Name 1", - description: "Description 1", id: assigns(:profile).id.to_s, - type: "profiles" + type: "profiles", + attributes: { + name: "Name 1", + description: "Description 1" + } } } @@ -182,10 +184,12 @@ module ActionController expected = { data: { - name: "Name 1", - description: "Description 1", id: assigns(:profile).id.to_s, - type: "profiles" + type: "profiles", + attributes: { + name: "Name 1", + description: "Description 1" + } } } @@ -217,10 +221,12 @@ module ActionController expected = { data: [ { - name: "Name 1", - description: "Description 1", id: assigns(:profiles).first.id.to_s, - type: "profiles" + type: "profiles", + attributes: { + name: "Name 1", + description: "Description 1" + } } ], meta: { diff --git a/test/adapter/json_api/belongs_to_test.rb b/test/adapter/json_api/belongs_to_test.rb index 3ce8074e..8a8aeef9 100644 --- a/test/adapter/json_api/belongs_to_test.rb +++ b/test/adapter/json_api/belongs_to_test.rb @@ -42,8 +42,10 @@ module ActiveModel expected = [{ id: "42", type: "posts", - title: 'New Post', - body: 'Body', + attributes: { + title: 'New Post', + body: 'Body', + }, links: { comments: { linkage: [ { type: "comments", id: "1" } ] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -58,7 +60,9 @@ module ActiveModel expected = [{ id: "42", type: "posts", - title: 'New Post', + attributes: { + title: 'New Post' + }, links: { comments: { linkage: [ { type: "comments", id: "1" } ] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -110,7 +114,9 @@ module ActiveModel { id: "1", type: "authors", - name: "Steve K.", + attributes: { + name: "Steve K." + }, links: { posts: { linkage: [] }, roles: { linkage: [] }, @@ -119,8 +125,10 @@ module ActiveModel },{ id: "42", type: "posts", - title: "New Post", - body: "Body", + attributes: { + title: "New Post", + body: "Body" + }, links: { comments: { linkage: [ { type: "comments", id: "1" } ] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -129,8 +137,10 @@ module ActiveModel }, { id: "43", type: "posts", - title: "Hello!!", - body: "Hello, world!!", + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, links: { comments: { linkage: [] }, blog: { linkage: { type: "blogs", id: "999" } }, diff --git a/test/adapter/json_api/collection_test.rb b/test/adapter/json_api/collection_test.rb index 36fb68e2..2426f439 100644 --- a/test/adapter/json_api/collection_test.rb +++ b/test/adapter/json_api/collection_test.rb @@ -29,8 +29,10 @@ module ActiveModel { id: "1", type: "posts", - title: "Hello!!", - body: "Hello, world!!", + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, links: { comments: { linkage: [] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -40,8 +42,10 @@ module ActiveModel { id: "2", type: "posts", - title: "New Post", - body: "Body", + attributes: { + title: "New Post", + body: "Body" + }, links: { comments: { linkage: [] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -60,7 +64,9 @@ module ActiveModel { id: "1", type: "posts", - title: "Hello!!", + attributes: { + title: "Hello!!" + }, links: { comments: { linkage: [] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -70,7 +76,9 @@ module ActiveModel { id: "2", type: "posts", - title: "New Post", + attributes: { + title: "New Post" + }, links: { comments: { linkage: [] }, blog: { linkage: { type: "blogs", id: "999" } }, diff --git a/test/adapter/json_api/has_many_test.rb b/test/adapter/json_api/has_many_test.rb index cdd4bf3e..da67dd37 100644 --- a/test/adapter/json_api/has_many_test.rb +++ b/test/adapter/json_api/has_many_test.rb @@ -43,7 +43,9 @@ module ActiveModel expected = [{ id: "1", type: "comments", - body: 'ZOMG A COMMENT', + attributes: { + body: 'ZOMG A COMMENT' + }, links: { post: { linkage: { type: "posts", id: "1" } }, author: { linkage: nil } @@ -51,7 +53,9 @@ module ActiveModel }, { id: "2", type: "comments", - body: 'ZOMG ANOTHER COMMENT', + attributes: { + body: 'ZOMG ANOTHER COMMENT' + }, links: { post: { linkage: { type: "posts", id: "1" } }, author: { linkage: nil } diff --git a/test/adapter/json_api/has_one_test.rb b/test/adapter/json_api/has_one_test.rb index 170caf84..1172f058 100644 --- a/test/adapter/json_api/has_one_test.rb +++ b/test/adapter/json_api/has_one_test.rb @@ -41,9 +41,11 @@ module ActiveModel expected = [ { id: "43", - rating: nil, type: "bios", - content:"AMS Contributor", + attributes: { + content:"AMS Contributor", + rating: nil + }, links: { author: { linkage: { type: "authors", id: "1" } } } diff --git a/test/adapter/json_api/linked_test.rb b/test/adapter/json_api/linked_test.rb index f9ac6f2b..271fb8a7 100644 --- a/test/adapter/json_api/linked_test.rb +++ b/test/adapter/json_api/linked_test.rb @@ -54,9 +54,11 @@ module ActiveModel data: [ { id: "10", - title: "Hello!!", - body: "Hello, world!!", type: "posts", + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, links: { comments: { linkage: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -65,9 +67,11 @@ module ActiveModel }, { id: "20", - title: "New Post", - body: "Body", type: "posts", + attributes: { + title: "New Post", + body: "Body" + }, links: { comments: { linkage: [] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -78,24 +82,30 @@ module ActiveModel included: [ { id: "1", - body: "ZOMG A COMMENT", type: "comments", + attributes: { + body: "ZOMG A COMMENT" + }, links: { post: { linkage: { type: "posts", id: "10" } }, author: { linkage: nil } } }, { id: "2", - body: "ZOMG ANOTHER COMMENT", type: "comments", + attributes: { + body: "ZOMG ANOTHER COMMENT", + }, links: { post: { linkage: { type: "posts", id: "10" } }, author: { linkage: nil } } }, { id: "1", - name: "Steve K.", type: "authors", + attributes: { + name: "Steve K." + }, links: { posts: { linkage: [ { type: "posts", id: "10" }, { type: "posts", id: "30" } ] }, roles: { linkage: [] }, @@ -103,16 +113,20 @@ module ActiveModel } }, { id: "1", - rating: nil, type: "bios", - content: "AMS Contributor", + attributes: { + content: "AMS Contributor", + rating: nil + }, links: { author: { linkage: { type: "authors", id: "1" } } } }, { id: "2", - name: "Tenderlove", type: "authors", + attributes: { + name: "Tenderlove" + }, links: { posts: { linkage: [ { type: "posts", id:"20" } ] }, roles: { linkage: [] }, @@ -120,9 +134,11 @@ module ActiveModel } }, { id: "2", - rating: nil, type: "bios", - content: "Rails Contributor", + attributes: { + rating: nil, + content: "Rails Contributor", + }, links: { author: { linkage: { type: "authors", id: "2" } } } @@ -148,7 +164,9 @@ module ActiveModel { id: "1", type: "authors", - name: "Steve K.", + attributes: { + name: "Steve K." + }, links: { posts: { linkage: [ { type: "posts", id: "10"}, { type: "posts", id: "30" }] }, roles: { linkage: [] }, @@ -157,8 +175,10 @@ module ActiveModel }, { id: "10", type: "posts", - title: "Hello!!", - body: "Hello, world!!", + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, links: { comments: { linkage: [ { type: "comments", id: "1"}, { type: "comments", id: "2" }] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -167,8 +187,10 @@ module ActiveModel }, { id: "30", type: "posts", - title: "Yet Another Post", - body: "Body", + attributes: { + title: "Yet Another Post", + body: "Body" + }, links: { comments: { linkage: [] }, blog: { linkage: { type: "blogs", id: "999" } }, @@ -208,9 +230,11 @@ module ActiveModel expected = [ { id: "10", - title: "Hello!!", - body: "Hello, world!!", type: "posts", + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, links: { comments: { linkage: [{type: "comments", id: "1"}, {type: "comments", id: "2"}] @@ -239,9 +263,11 @@ module ActiveModel expected = { data: { id: "10", - title: "Hello!!", - body: "Hello, world!!", type: "posts", + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, links: { comments: { linkage: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] }, author: { linkage: nil }