Skip to content

Commit 92dd0ed

Browse files
committed
add relationship level links and meta options
1 parent b2cd7bb commit 92dd0ed

File tree

5 files changed

+261
-1
lines changed

5 files changed

+261
-1
lines changed

lib/active_model/serializer/adapter/json_api.rb

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,41 @@ def relationship_value_for(serializer, options = {})
173173
end
174174
end
175175

176+
def relationship_links_for(name, owner, options = {})
177+
options[:links].inject({}) do |hash, (key, link)|
178+
hash[key] = if link.is_a? Proc
179+
link.call(owner, name)
180+
else
181+
link
182+
end
183+
184+
hash
185+
end
186+
end
187+
188+
def relationship_meta_for(name, owner, options = {})
189+
if options[:meta].is_a? Proc
190+
options[:meta].call(owner, name)
191+
else
192+
options[:meta]
193+
end
194+
end
195+
176196
def relationships_for(serializer)
177197
serializer.associations.each_with_object({}) do |association, hash|
178-
hash[association.key] = { data: relationship_value_for(association.serializer, association.options) }
198+
hash[association.key] = {}
199+
200+
if association.options.fetch(:data, true)
201+
hash[association.key][:data] = relationship_value_for(association.serializer, association.options)
202+
end
203+
204+
if association.options.fetch(:links, false)
205+
hash[association.key][:links] = relationship_links_for(association.name, serializer.object, association.options)
206+
end
207+
208+
if association.options.fetch(:meta, false)
209+
hash[association.key][:meta] = relationship_meta_for(association.name, serializer.object, association.options)
210+
end
179211
end
180212
end
181213

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
require 'test_helper'
2+
3+
module ActionController
4+
module Serialization
5+
class JsonApiHasManyLinksTest < ActionController::TestCase
6+
LinkTagSerializer = Class.new(ActiveModel::Serializer) do
7+
has_many :posts, links: { related: -> (object, name) { "http://test.host/tags/#{object.id}/#{name}" } }, data: false
8+
end
9+
10+
class MyController < ActionController::Base
11+
def render_resource_with_has_many_association
12+
@tag = Tag.new(id: 1)
13+
@tag.posts = []
14+
render json: @tag, adapter: :json_api, serializer: LinkTagSerializer
15+
end
16+
end
17+
18+
tests MyController
19+
20+
def test_render_resource_with_has_many_association
21+
get :render_resource_with_has_many_association
22+
expected = {
23+
data: {
24+
id: "1",
25+
type: "tags",
26+
relationships: {
27+
posts: {
28+
links: {
29+
related: "http://test.host/tags/1/posts"
30+
}
31+
}
32+
}
33+
}
34+
}
35+
assert_equal expected.to_json, response.body
36+
end
37+
end
38+
39+
class JsonApiHasManyLinksWithDataTest < ActionController::TestCase
40+
LinkTagSerializer = Class.new(ActiveModel::Serializer) do
41+
has_many :posts, links: { related: -> (object, name) { "http://test.host/tags/#{object.id}/#{name}" } }
42+
end
43+
44+
class MyController < ActionController::Base
45+
def render_resource_with_has_many_association
46+
@tag = Tag.new(id: 1)
47+
@tag.posts = []
48+
render json: @tag, adapter: :json_api, serializer: LinkTagSerializer
49+
end
50+
end
51+
52+
tests MyController
53+
54+
def test_render_resource_with_has_many_association
55+
get :render_resource_with_has_many_association
56+
expected = {
57+
data: {
58+
id: "1",
59+
type: "tags",
60+
relationships: {
61+
posts: {
62+
data: [],
63+
links: {
64+
related: "http://test.host/tags/1/posts"
65+
}
66+
}
67+
}
68+
}
69+
}
70+
assert_equal expected.to_json, response.body
71+
end
72+
end
73+
end
74+
end
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
require 'test_helper'
2+
3+
module ActionController
4+
module Serialization
5+
class JsonApiHasManyMetaTest < ActionController::TestCase
6+
MetaTagSerializer = Class.new(ActiveModel::Serializer) do
7+
has_many :posts, meta: -> (object, name) { { page: "1" } }
8+
end
9+
10+
class MyController < ActionController::Base
11+
def render_resource_with_has_many_association
12+
@tag = Tag.new(id: 1)
13+
@tag.posts = []
14+
render json: @tag, adapter: :json_api, serializer: MetaTagSerializer
15+
end
16+
end
17+
18+
tests MyController
19+
20+
def test_render_resource_with_has_many_association
21+
get :render_resource_with_has_many_association
22+
expected = {
23+
data: {
24+
id: "1",
25+
type: "tags",
26+
relationships: {
27+
posts: {
28+
data: [],
29+
meta: {
30+
page: "1"
31+
}
32+
}
33+
}
34+
}
35+
}
36+
assert_equal expected.to_json, response.body
37+
end
38+
end
39+
end
40+
end
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
require 'test_helper'
2+
3+
module ActionController
4+
module Serialization
5+
class JsonApiHasOneLinksTest < ActionController::TestCase
6+
LinkTagSerializer = Class.new(ActiveModel::Serializer) do
7+
has_one :post, links: { related: -> (object, name) { "http://test.host/tags/#{object.id}/#{name}" } }, data: false
8+
end
9+
10+
class MyController < ActionController::Base
11+
def render_resource_with_has_one_association
12+
@tag = Tag.new(id: 1)
13+
@tag.post = Post.new(id: 1)
14+
render json: @tag, adapter: :json_api, serializer: LinkTagSerializer
15+
end
16+
end
17+
18+
tests MyController
19+
20+
def test_render_resource_with_has_one_association
21+
get :render_resource_with_has_one_association
22+
expected = {
23+
data: {
24+
id: "1",
25+
type: "tags",
26+
relationships: {
27+
post: {
28+
links: {
29+
related: "http://test.host/tags/1/post"
30+
}
31+
}
32+
}
33+
}
34+
}
35+
assert_equal expected.to_json, response.body
36+
end
37+
end
38+
39+
class JsonApiHasOneLinksWithDataTest < ActionController::TestCase
40+
LinkTagSerializer = Class.new(ActiveModel::Serializer) do
41+
has_one :post, links: { related: -> (object, name) { "http://test.host/tags/#{object.id}/#{name}" } }
42+
end
43+
44+
class MyController < ActionController::Base
45+
def render_resource_with_has_one_association
46+
@tag = Tag.new(id: 1)
47+
@tag.post = Post.new(id: 1)
48+
render json: @tag, adapter: :json_api, serializer: LinkTagSerializer
49+
end
50+
end
51+
52+
tests MyController
53+
54+
def test_render_resource_with_has_one_association
55+
get :render_resource_with_has_one_association
56+
expected = {
57+
data: {
58+
id: "1",
59+
type: "tags",
60+
relationships: {
61+
post: {
62+
data: { id: "1", type: "posts" },
63+
links: {
64+
related: "http://test.host/tags/1/post"
65+
}
66+
}
67+
}
68+
}
69+
}
70+
assert_equal expected.to_json, response.body
71+
end
72+
end
73+
end
74+
end
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
require 'test_helper'
2+
3+
module ActionController
4+
module Serialization
5+
class JsonApiHasOneMetaTest < ActionController::TestCase
6+
MetaTagSerializer = Class.new(ActiveModel::Serializer) do
7+
has_one :post, meta: -> (object, name) { { deleted: true } }
8+
end
9+
10+
class MyController < ActionController::Base
11+
def render_resource_with_has_one_association
12+
@tag = Tag.new(id: 1)
13+
@tag.post = Post.new(id: 1)
14+
render json: @tag, adapter: :json_api, serializer: MetaTagSerializer
15+
end
16+
end
17+
18+
tests MyController
19+
20+
def test_render_resource_with_has_one_association
21+
get :render_resource_with_has_one_association
22+
expected = {
23+
data: {
24+
id: "1",
25+
type: "tags",
26+
relationships: {
27+
post: {
28+
data: { id: "1", type: "posts" },
29+
meta: {
30+
deleted: true
31+
}
32+
}
33+
}
34+
}
35+
}
36+
assert_equal expected.to_json, response.body
37+
end
38+
end
39+
end
40+
end

0 commit comments

Comments
 (0)