Skip to content

Commit

Permalink
Adds support for top-level links to JsonApi adapter
Browse files Browse the repository at this point in the history
http://jsonapi.org/format/#document-top-level

fix failing tests

support for top-level links limited to jsonapi adapter
  • Loading branch information
leandrocp committed Aug 6, 2015
1 parent 03ddeee commit 1dcb3b3
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ test/version_tmp
tmp
*.swp
.ruby-version
tags
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
* adds cache support to attributes and associations [@joaomdmoura]
* uses model name to determine the type [@lsylvester]
* remove root key option and split JSON adapter [@joaomdmoura]
* adds FlattenJSON as default adapter [@joaomdmoura]
* adds FlattenJSON as default adapter [@joaomdmoura]
* adds support for `links` at top level of JsonApi adapter [@leandrocp]
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ render json: @post, meta: { total: 10 }, meta_key: "custom_meta"

`meta` will only be included in your response if you are using an Adapter that supports `root`, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have `root`.

### Links

A top-level `links` object may be specified in the `render` call:

```ruby
render json: @post, links: { self: "/posts/1" }
```

### Overriding association methods

If you want to override any association, you can use:
Expand Down
3 changes: 2 additions & 1 deletion lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,15 @@ def self.root_name
name.demodulize.underscore.sub(/_serializer$/, '') if name
end

attr_accessor :object, :root, :meta, :meta_key, :scope
attr_accessor :object, :root, :meta, :meta_key, :links, :scope

def initialize(object, options = {})
@object = object
@options = options
@root = options[:root]
@meta = options[:meta]
@meta_key = options[:meta_key]
@links = options[:links]
@scope = options[:scope]

scope_name = options[:scope_name]
Expand Down
5 changes: 5 additions & 0 deletions lib/active_model/serializer/adapter/json_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def serializable_hash(options = nil)
@hash[:data] = attributes_for_serializer(serializer, options)
add_resource_relationships(@hash[:data], serializer)
end
@hash[:links] = attributes_for_top_level_links(serializer) if serializer.links
@hash
end

Expand Down Expand Up @@ -157,6 +158,10 @@ def add_resource_relationships(attrs, serializer, options = {})
end
end
end

def attributes_for_top_level_links(serializer)
serializer.links
end
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion lib/active_model/serializer/array_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class ArraySerializer
include Enumerable
delegate :each, to: :@objects

attr_reader :root, :meta, :meta_key
attr_reader :root, :meta, :meta_key, :links

def initialize(objects, options = {})
@root = options[:root]
Expand All @@ -24,6 +24,7 @@ def initialize(objects, options = {})
end
@meta = options[:meta]
@meta_key = options[:meta_key]
@links = options[:links]
end

def json_key
Expand Down
34 changes: 34 additions & 0 deletions test/action_controller/serialization_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ def render_array_using_implicit_serializer_and_meta
end
end

def render_array_using_implicit_serializer_and_links
with_adapter ActiveModel::Serializer::Adapter::JsonApi do

@profiles = [
Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
]

render json: @profiles, links: { self: "/profiles/1" }
end
end

def render_object_with_cache_enabled
@comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' })
@author = Author.new(id: 1, name: 'Joao Moura.')
Expand Down Expand Up @@ -266,6 +277,29 @@ def test_render_array_using_implicit_serializer_and_meta
assert_equal expected.to_json, @response.body
end

def test_render_array_using_implicit_serializer_and_links
get :render_array_using_implicit_serializer_and_links

expected = {
data: [
{
id: assigns(:profiles).first.id.to_s,
type: "profiles",
attributes: {
name: "Name 1",
description: "Description 1"
}
}
],
links: {
self: "/profiles/1"
}
}

assert_equal 'application/json', @response.content_type
assert_equal expected.to_json, @response.body
end

def test_render_with_cache_enable
expected = {
id: 1,
Expand Down
6 changes: 6 additions & 0 deletions test/array_serializer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ def test_meta_and_meta_key_attr_readers
assert_equal @serializer.meta_key, "the meta key"
end

def test_links_attr_reader
@serializer = ArraySerializer.new([@comment, @post], :links => {"self" => "/array/1"})

assert_equal @serializer.links, {"self" => "/array/1"}
end

def test_root_default
@serializer = ArraySerializer.new([@comment, @post])
assert_equal @serializer.root, nil
Expand Down
62 changes: 62 additions & 0 deletions test/serializers/links_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require 'test_helper'

module ActiveModel
class Serializer
class LinksTest < Minitest::Test
def setup
ActionController::Base.cache_store.clear
@blog = Blog.new(id: 1,
name: 'AMS Hints',
writer: Author.new(id: 2, name: "Steve"),
articles: [Post.new(id: 3, title: "AMS")])
end

def test_links_is_present_with_root
serializer = AlternateBlogSerializer.new(@blog, :links => {:self => "/blogs/1"})
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
expected = {
data: {
id: "1",
type: "blogs",
attributes: {
title: "AMS Hints"
}
},
links: {
self: "/blogs/1"
}
}
assert_equal expected, adapter.as_json
end

def test_links_is_not_present_when_not_declared
serializer = AlternateBlogSerializer.new(@blog)
adapter = ActiveModel::Serializer::Adapter::JsonApi.new(serializer)
expected = {
data: {
id: "1",
type: "blogs",
attributes: {
title: "AMS Hints"
}
}
}
assert_equal expected, adapter.as_json
end

def test_links_is_not_present_on_flattenjson_adapter
serializer = AlternateBlogSerializer.new(@blog, :links => {:self => "/blogs/1"})
adapter = ActiveModel::Serializer::Adapter::FlattenJson.new(serializer)
expected = {:id=>1, :title=>"AMS Hints"}
assert_equal expected, adapter.as_json
end

def test_links_is_not_present_on_json_adapter
serializer = AlternateBlogSerializer.new(@blog, :links => {:self => "/blogs/1"})
adapter = ActiveModel::Serializer::Adapter::Json.new(serializer)
expected = {:blog=>{:id=>1, :title=>"AMS Hints"}}
assert_equal expected, adapter.as_json
end
end
end
end

0 comments on commit 1dcb3b3

Please sign in to comment.