diff --git a/README.md b/README.md index 05d836694..5d4cd6c43 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ AMS does this through two components: **serializers** and **adapters**. Serializers describe _which_ attributes and relationships should be serialized. Adapters describe _how_ attributes and relationships should be serialized. -By default AMS will use the JsonApi Adapter that follows RC3 of the format specified in [jsonapi.org/format](http://jsonapi.org/format). +By default AMS will use the JsonApi Adapter that follows RC4 of the format specified in [jsonapi.org/format](http://jsonapi.org/format). Check how to change the adapter in the sections bellow. # RELEASE CANDIDATE, PLEASE READ @@ -178,7 +178,7 @@ end #### JSONAPI -This adapter follows RC3 of the format specified in +This adapter follows RC4 of the format specified in [jsonapi.org/format](http://jsonapi.org/format). It will include the associated resources in the `"included"` member when the resource names are included in the `include` option. diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 6cc695499..8028a0757 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -29,7 +29,7 @@ def serializable_hash(options = {}) end else @hash[:data] = attributes_for_serializer(serializer, @options) - add_resource_links(@hash[:data], serializer) + add_resource_relationships(@hash[:data], serializer) end @hash end @@ -41,18 +41,18 @@ def fragment_cache(cached_hash, non_cached_hash) private - def add_links(resource, name, serializers) - resource[:links] ||= {} - resource[:links][name] ||= { linkage: [] } - resource[:links][name][:linkage] += serializers.map { |serializer| { type: serializer.type, id: serializer.id.to_s } } + def add_relationships(resource, name, serializers) + resource[:relationships] ||= {} + resource[:relationships][name] ||= { data: [] } + resource[:relationships][name][:data] += serializers.map { |serializer| { type: serializer.type, id: serializer.id.to_s } } end - def add_link(resource, name, serializer, val=nil) - resource[:links] ||= {} - resource[:links][name] = { linkage: nil } + def add_relationship(resource, name, serializer, val=nil) + resource[:relationships] ||= {} + resource[:relationships][name] = { data: nil } if serializer && serializer.object - resource[:links][name][:linkage] = { type: serializer.type, id: serializer.id.to_s } + resource[:relationships][name][:data] = { type: serializer.type, id: serializer.id.to_s } end end @@ -68,7 +68,7 @@ def add_included(resource_name, serializers, parent = nil) serializers.each do |serializer| attrs = attributes_for_serializer(serializer, @options) - add_resource_links(attrs, serializer, add_included: false) + add_resource_relationships(attrs, serializer, add_included: false) @hash[:included].push(attrs) unless @hash[:included].include?(attrs) end @@ -85,26 +85,31 @@ def attributes_for_serializer(serializer, options) 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}$") @@ -123,19 +128,19 @@ def check_assoc(assoc) end end - def add_resource_links(attrs, serializer, options = {}) + def add_resource_relationships(attrs, serializer, options = {}) options[:add_included] = options.fetch(:add_included, true) serializer.each_association do |name, association, opts| - attrs[:links] ||= {} + attrs[:relationships] ||= {} if association.respond_to?(:each) - add_links(attrs, name, association) + add_relationships(attrs, name, association) else if opts[:virtual_value] - add_link(attrs, name, nil, opts[:virtual_value]) + add_relationship(attrs, name, nil, opts[:virtual_value]) else - add_link(attrs, name, association) + add_relationship(attrs, name, association) end end 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 75630b619..6ce1c1848 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 @@ def fragment_cache(root, cached_hash, non_cached_hash) 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 07bdf0a72..1ff03cf24 100644 --- a/test/action_controller/adapter_selector_test.rb +++ b/test/action_controller/adapter_selector_test.rb @@ -32,10 +32,12 @@ def test_render_using_adapter_override 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 d3a1f8447..559b2dd96 100644 --- a/test/action_controller/json_api_linked_test.rb +++ b/test/action_controller/json_api_linked_test.rb @@ -91,7 +91,7 @@ def test_render_resource_with_include 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,29 +101,35 @@ def test_render_resource_with_nested_has_many_include { "id" => "1", "type" => "authors", - "name" => "Steve K.", - "links" => { - "posts" => { "linkage" => [] }, - "roles" => { "linkage" => [{ "type" =>"roles", "id" => "1" }, { "type" =>"roles", "id" => "2" }] }, - "bio" => { "linkage" => nil } + "attributes" => { + "name" => "Steve K." + }, + "relationships" => { + "posts" => { "data" => [] }, + "roles" => { "data" => [{ "type" =>"roles", "id" => "1" }, { "type" =>"roles", "id" => "2" }] }, + "bio" => { "data" => nil } } }, { "id" => "1", "type" => "roles", - "name" => "admin", - "description" => nil, - "slug" => "admin-1", - "links" => { - "author" => { "linkage" => { "type" =>"authors", "id" => "1" } } + "attributes" => { + "name" => "admin", + "description" => nil, + "slug" => "admin-1" + }, + "relationships" => { + "author" => { "data" => { "type" =>"authors", "id" => "1" } } } }, { "id" => "2", "type" => "roles", - "name" => "colab", - "description" => nil, - "slug" => "colab-2", - "links" => { - "author" => { "linkage" => { "type" =>"authors", "id" => "1" } } + "attributes" => { + "name" => "colab", + "description" => nil, + "slug" => "colab-2" + }, + "relationships" => { + "author" => { "data" => { "type" =>"authors", "id" => "1" } } } } ] @@ -135,7 +141,7 @@ def test_render_resource_with_nested_include 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 7a406e7a3..2af0a1fa9 100644 --- a/test/action_controller/serialization_scope_name_test.rb +++ b/test/action_controller/serialization_scope_name_test.rb @@ -27,7 +27,7 @@ def render_new_user 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 @@ def render_new_user 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 ff84655cb..ad20bc3ed 100644 --- a/test/action_controller/serialization_test.rb +++ b/test/action_controller/serialization_test.rb @@ -166,10 +166,12 @@ def test_render_using_default_root 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 @@ def test_render_using_custom_root_in_adapter_with_a_default 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 @@ def test_render_array_using_implicit_serializer_and_meta 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 3ce8074e4..967b53e9a 100644 --- a/test/adapter/json_api/belongs_to_test.rb +++ b/test/adapter/json_api/belongs_to_test.rb @@ -32,9 +32,9 @@ def setup end def test_includes_post_id - expected = { linkage: { type: "posts", id: "42" } } + expected = { data: { type: "posts", id: "42" } } - assert_equal(expected, @adapter.serializable_hash[:data][:links][:post]) + assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:post]) end def test_includes_linked_post @@ -42,12 +42,14 @@ def test_includes_linked_post expected = [{ id: "42", type: "posts", - title: 'New Post', - body: 'Body', - links: { - comments: { linkage: [ { type: "comments", id: "1" } ] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: 'New Post', + body: 'Body', + }, + relationships: { + comments: { data: [ { type: "comments", id: "1" } ] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } }] assert_equal expected, @adapter.serializable_hash[:included] @@ -58,11 +60,13 @@ def test_limiting_linked_post_fields expected = [{ id: "42", type: "posts", - title: 'New Post', - links: { - comments: { linkage: [ { type: "comments", id: "1" } ] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: 'New Post' + }, + relationships: { + comments: { data: [ { type: "comments", id: "1" } ] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } }] assert_equal expected, @adapter.serializable_hash[:included] @@ -72,22 +76,22 @@ def test_include_nil_author serializer = PostSerializer.new(@anonymous_post) adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) - assert_equal({comments: { linkage: [] }, blog: { linkage: { type: "blogs", id: "999" } }, author: { linkage: nil }}, adapter.serializable_hash[:data][:links]) + assert_equal({comments: { data: [] }, blog: { data: { type: "blogs", id: "999" } }, author: { data: nil }}, adapter.serializable_hash[:data][:relationships]) end def test_include_type_for_association_when_different_than_name serializer = BlogSerializer.new(@blog) adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) - links = adapter.serializable_hash[:data][:links] + relationships = adapter.serializable_hash[:data][:relationships] expected = { writer: { - linkage: { + data: { type: "authors", id: "1" } }, articles: { - linkage: [ + data: [ { type: "posts", id: "42" @@ -99,7 +103,7 @@ def test_include_type_for_association_when_different_than_name ] } } - assert_equal expected, links + assert_equal expected, relationships end def test_include_linked_resources_with_type_name @@ -110,31 +114,37 @@ def test_include_linked_resources_with_type_name { id: "1", type: "authors", - name: "Steve K.", - links: { - posts: { linkage: [] }, - roles: { linkage: [] }, - bio: { linkage: nil } + attributes: { + name: "Steve K." + }, + relationships: { + posts: { data: [] }, + roles: { data: [] }, + bio: { data: nil } } },{ id: "42", type: "posts", - title: "New Post", - body: "Body", - links: { - comments: { linkage: [ { type: "comments", id: "1" } ] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: "New Post", + body: "Body" + }, + relationships: { + comments: { data: [ { type: "comments", id: "1" } ] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } }, { id: "43", type: "posts", - title: "Hello!!", - body: "Hello, world!!", - links: { - comments: { linkage: [] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: nil } + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, + relationships: { + comments: { data: [] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: nil } } } ] diff --git a/test/adapter/json_api/collection_test.rb b/test/adapter/json_api/collection_test.rb index 36fb68e28..f17285fa1 100644 --- a/test/adapter/json_api/collection_test.rb +++ b/test/adapter/json_api/collection_test.rb @@ -29,23 +29,27 @@ def test_include_multiple_posts { id: "1", type: "posts", - title: "Hello!!", - body: "Hello, world!!", - links: { - comments: { linkage: [] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, + relationships: { + comments: { data: [] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } }, { id: "2", type: "posts", - title: "New Post", - body: "Body", - links: { - comments: { linkage: [] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: "New Post", + body: "Body" + }, + relationships: { + comments: { data: [] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } } ] @@ -60,21 +64,25 @@ def test_limiting_fields { id: "1", type: "posts", - title: "Hello!!", - links: { - comments: { linkage: [] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: "Hello!!" + }, + relationships: { + comments: { data: [] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } }, { id: "2", type: "posts", - title: "New Post", - links: { - comments: { linkage: [] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: "New Post" + }, + relationships: { + comments: { data: [] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } } ] diff --git a/test/adapter/json_api/has_many_embed_ids_test.rb b/test/adapter/json_api/has_many_embed_ids_test.rb index 50f367c17..7dd132c7c 100644 --- a/test/adapter/json_api/has_many_embed_ids_test.rb +++ b/test/adapter/json_api/has_many_embed_ids_test.rb @@ -26,13 +26,13 @@ def setup def test_includes_comment_ids expected = { - linkage: [ + data: [ { type: "posts", id: "1"}, { type: "posts", id: "2"} ] } - assert_equal(expected, @adapter.serializable_hash[:data][:links][:posts]) + assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:posts]) end def test_no_includes_linked_comments diff --git a/test/adapter/json_api/has_many_explicit_serializer_test.rb b/test/adapter/json_api/has_many_explicit_serializer_test.rb index 4ff53728e..2adb0eb53 100644 --- a/test/adapter/json_api/has_many_explicit_serializer_test.rb +++ b/test/adapter/json_api/has_many_explicit_serializer_test.rb @@ -30,13 +30,13 @@ def setup def test_includes_comment_ids expected = { - linkage: [ + data: [ { type: 'comments', id: '1' }, { type: 'comments', id: '2' } ] } - assert_equal(expected, @adapter.serializable_hash[:data][:links][:comments]) + assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:comments]) end def test_includes_linked_data @@ -45,22 +45,22 @@ def test_includes_linked_data { id: '1', type: 'comments', - links: { - post: { linkage: { type: 'posts', id: @post.id.to_s } } + relationships: { + post: { data: { type: 'posts', id: @post.id.to_s } } } }, { id: '2', type: 'comments', - links: { - post: { linkage: { type: 'posts', id: @post.id.to_s } } + relationships: { + post: { data: { type: 'posts', id: @post.id.to_s } } } }, { id: @author.id.to_s, type: "authors", - links: { - posts: { linkage: [ {type: "posts", id: @post.id.to_s } ] } + relationships: { + posts: { data: [ {type: "posts", id: @post.id.to_s } ] } } } ] @@ -70,26 +70,26 @@ def test_includes_linked_data def test_includes_author_id expected = { - linkage: { type: "authors", id: @author.id.to_s } + data: { type: "authors", id: @author.id.to_s } } - assert_equal(expected, @adapter.serializable_hash[:data][:links][:author]) + assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:author]) end def test_explicit_serializer_with_null_resource @post.author = nil - expected = { linkage: nil } + expected = { data: nil } - assert_equal(expected, @adapter.serializable_hash[:data][:links][:author]) + assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:author]) end def test_explicit_serializer_with_null_collection @post.comments = [] - expected = { linkage: [] } + expected = { data: [] } - assert_equal(expected, @adapter.serializable_hash[:data][:links][:comments]) + assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:comments]) end end end diff --git a/test/adapter/json_api/has_many_test.rb b/test/adapter/json_api/has_many_test.rb index cdd4bf3e5..a544fc800 100644 --- a/test/adapter/json_api/has_many_test.rb +++ b/test/adapter/json_api/has_many_test.rb @@ -33,9 +33,9 @@ def setup end def test_includes_comment_ids - expected = { linkage: [ { type: "comments", id: "1" }, { type: "comments", id: "2" } ] } + expected = { data: [ { type: "comments", id: "1" }, { type: "comments", id: "2" } ] } - assert_equal(expected, @adapter.serializable_hash[:data][:links][:comments]) + assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:comments]) end def test_includes_linked_comments @@ -43,18 +43,22 @@ def test_includes_linked_comments expected = [{ id: "1", type: "comments", - body: 'ZOMG A COMMENT', - links: { - post: { linkage: { type: "posts", id: "1" } }, - author: { linkage: nil } + attributes: { + body: 'ZOMG A COMMENT' + }, + relationships: { + post: { data: { type: "posts", id: "1" } }, + author: { data: nil } } }, { id: "2", type: "comments", - body: 'ZOMG ANOTHER COMMENT', - links: { - post: { linkage: { type: "posts", id: "1" } }, - author: { linkage: nil } + attributes: { + body: 'ZOMG ANOTHER COMMENT' + }, + relationships: { + post: { data: { type: "posts", id: "1" } }, + author: { data: nil } } }] assert_equal expected, @adapter.serializable_hash[:included] @@ -65,16 +69,16 @@ def test_limit_fields_of_linked_comments expected = [{ id: "1", type: "comments", - links: { - post: { linkage: { type: "posts", id: "1" } }, - author: { linkage: nil } + relationships: { + post: { data: { type: "posts", id: "1" } }, + author: { data: nil } } }, { id: "2", type: "comments", - links: { - post: { linkage: { type: "posts", id: "1" } }, - author: { linkage: nil } + relationships: { + post: { data: { type: "posts", id: "1" } }, + author: { data: nil } } }] assert_equal expected, @adapter.serializable_hash[:included] @@ -90,9 +94,9 @@ def test_no_include_linked_if_comments_is_empty def test_include_type_for_association_when_different_than_name serializer = BlogSerializer.new(@blog) adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) - actual = adapter.serializable_hash[:data][:links][:articles] + actual = adapter.serializable_hash[:data][:relationships][:articles] expected = { - linkage: [{ + data: [{ type: "posts", id: "1" }] diff --git a/test/adapter/json_api/has_one_test.rb b/test/adapter/json_api/has_one_test.rb index 170caf84f..195d56820 100644 --- a/test/adapter/json_api/has_one_test.rb +++ b/test/adapter/json_api/has_one_test.rb @@ -30,9 +30,9 @@ def setup end def test_includes_bio_id - expected = { linkage: { type: "bios", id: "43" } } + expected = { data: { type: "bios", id: "43" } } - assert_equal(expected, @adapter.serializable_hash[:data][:links][:bio]) + assert_equal(expected, @adapter.serializable_hash[:data][:relationships][:bio]) end def test_includes_linked_bio @@ -41,11 +41,13 @@ def test_includes_linked_bio expected = [ { id: "43", - rating: nil, type: "bios", - content:"AMS Contributor", - links: { - author: { linkage: { type: "authors", id: "1" } } + attributes: { + content:"AMS Contributor", + rating: nil + }, + relationships: { + author: { data: { type: "authors", id: "1" } } } } ] diff --git a/test/adapter/json_api/linked_test.rb b/test/adapter/json_api/linked_test.rb index f9ac6f2b6..ff27fac80 100644 --- a/test/adapter/json_api/linked_test.rb +++ b/test/adapter/json_api/linked_test.rb @@ -54,77 +54,93 @@ def test_include_multiple_posts_and_linked_array data: [ { id: "10", - title: "Hello!!", - body: "Hello, world!!", type: "posts", - links: { - comments: { linkage: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, + relationships: { + comments: { data: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } }, { id: "20", - title: "New Post", - body: "Body", type: "posts", - links: { - comments: { linkage: [] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "2" } } + attributes: { + title: "New Post", + body: "Body" + }, + relationships: { + comments: { data: [] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "2" } } } } ], included: [ { id: "1", - body: "ZOMG A COMMENT", type: "comments", - links: { - post: { linkage: { type: "posts", id: "10" } }, - author: { linkage: nil } + attributes: { + body: "ZOMG A COMMENT" + }, + relationships: { + post: { data: { type: "posts", id: "10" } }, + author: { data: nil } } }, { id: "2", - body: "ZOMG ANOTHER COMMENT", type: "comments", - links: { - post: { linkage: { type: "posts", id: "10" } }, - author: { linkage: nil } + attributes: { + body: "ZOMG ANOTHER COMMENT", + }, + relationships: { + post: { data: { type: "posts", id: "10" } }, + author: { data: nil } } }, { id: "1", - name: "Steve K.", type: "authors", - links: { - posts: { linkage: [ { type: "posts", id: "10" }, { type: "posts", id: "30" } ] }, - roles: { linkage: [] }, - bio: { linkage: { type: "bios", id: "1" } } + attributes: { + name: "Steve K." + }, + relationships: { + posts: { data: [ { type: "posts", id: "10" }, { type: "posts", id: "30" } ] }, + roles: { data: [] }, + bio: { data: { type: "bios", id: "1" } } } }, { id: "1", - rating: nil, type: "bios", - content: "AMS Contributor", - links: { - author: { linkage: { type: "authors", id: "1" } } + attributes: { + content: "AMS Contributor", + rating: nil + }, + relationships: { + author: { data: { type: "authors", id: "1" } } } }, { id: "2", - name: "Tenderlove", type: "authors", - links: { - posts: { linkage: [ { type: "posts", id:"20" } ] }, - roles: { linkage: [] }, - bio: { linkage: { type: "bios", id: "2" } } + attributes: { + name: "Tenderlove" + }, + relationships: { + posts: { data: [ { type: "posts", id:"20" } ] }, + roles: { data: [] }, + bio: { data: { type: "bios", id: "2" } } } }, { id: "2", - rating: nil, type: "bios", - content: "Rails Contributor", - links: { - author: { linkage: { type: "authors", id: "2" } } + attributes: { + rating: nil, + content: "Rails Contributor", + }, + relationships: { + author: { data: { type: "authors", id: "2" } } } } ] @@ -148,31 +164,37 @@ def test_include_multiple_posts_and_linked { id: "1", type: "authors", - name: "Steve K.", - links: { - posts: { linkage: [ { type: "posts", id: "10"}, { type: "posts", id: "30" }] }, - roles: { linkage: [] }, - bio: { linkage: { type: "bios", id: "1" }} + attributes: { + name: "Steve K." + }, + relationships: { + posts: { data: [ { type: "posts", id: "10"}, { type: "posts", id: "30" }] }, + roles: { data: [] }, + bio: { data: { type: "bios", id: "1" }} } }, { id: "10", type: "posts", - title: "Hello!!", - body: "Hello, world!!", - links: { - comments: { linkage: [ { type: "comments", id: "1"}, { type: "comments", id: "2" }] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, + relationships: { + comments: { data: [ { type: "comments", id: "1"}, { type: "comments", id: "2" }] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } }, { id: "30", type: "posts", - title: "Yet Another Post", - body: "Body", - links: { - comments: { linkage: [] }, - blog: { linkage: { type: "blogs", id: "999" } }, - author: { linkage: { type: "authors", id: "1" } } + attributes: { + title: "Yet Another Post", + body: "Body" + }, + relationships: { + comments: { data: [] }, + blog: { data: { type: "blogs", id: "999" } }, + author: { data: { type: "authors", id: "1" } } } } ] @@ -186,16 +208,16 @@ def test_ignore_model_namespace_for_linked_resource_type spammy_post.related = [Spam::UnrelatedLink.new(id: 456)] serializer = SpammyPostSerializer.new(spammy_post) adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer) - links = adapter.serializable_hash[:data][:links] + relationships = adapter.serializable_hash[:data][:relationships] expected = { related: { - linkage: [{ + data: [{ type: 'unrelated_links', id: '456' }] } } - assert_equal expected, links + assert_equal expected, relationships end def test_multiple_references_to_same_resource @@ -208,18 +230,20 @@ def test_multiple_references_to_same_resource expected = [ { id: "10", - title: "Hello!!", - body: "Hello, world!!", type: "posts", - links: { + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, + relationships: { comments: { - linkage: [{type: "comments", id: "1"}, {type: "comments", id: "2"}] + data: [{type: "comments", id: "1"}, {type: "comments", id: "2"}] }, blog: { - linkage: {type: "blogs", id: "999"} + data: {type: "blogs", id: "999"} }, author: { - linkage: {type: "authors", id: "1"} + data: {type: "authors", id: "1"} } } } @@ -239,12 +263,14 @@ def test_nil_link_with_specified_serializer expected = { data: { id: "10", - title: "Hello!!", - body: "Hello, world!!", type: "posts", - links: { - comments: { linkage: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] }, - author: { linkage: nil } + attributes: { + title: "Hello!!", + body: "Hello, world!!" + }, + relationships: { + comments: { data: [ { type: "comments", id: '1' }, { type: "comments", id: '2' } ] }, + author: { data: nil } } } }