Skip to content

Commit 55ff9ac

Browse files
committed
Merge pull request #1297 from beauby/fix-jsonapi-fields
Fix `fields` option to restrict relationships as well.
2 parents f3403c3 + b5aecfd commit 55ff9ac

File tree

6 files changed

+99
-13
lines changed

6 files changed

+99
-13
lines changed

lib/active_model/serializer/adapter/json_api.rb

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,7 @@ def object
4444
def initialize(serializer, options = {})
4545
super
4646
@include_tree = IncludeTree.from_include_args(options[:include])
47-
48-
fields = options.delete(:fields)
49-
if fields
50-
@fieldset = ActiveModel::Serializer::Fieldset.new(fields)
51-
else
52-
@fieldset = options[:fieldset]
53-
end
47+
@fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields))
5448
end
5549

5650
def serializable_hash(options = nil)
@@ -174,7 +168,10 @@ def relationship_value_for(serializer, options = {})
174168
end
175169

176170
def relationships_for(serializer)
177-
serializer.associations.each_with_object({}) do |association, hash|
171+
resource_type = resource_identifier_type_for(serializer)
172+
requested_associations = fieldset.fields_for(resource_type) || '*'
173+
include_tree = IncludeTree.from_include_args(requested_associations)
174+
serializer.associations(include_tree).each_with_object({}) do |association, hash|
178175
hash[association.key] = { data: relationship_value_for(association.serializer, association.options) }
179176
end
180177
end

lib/active_model/serializer/fieldset.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module ActiveModel
22
class Serializer
33
class Fieldset
44
def initialize(fields)
5-
@raw_fields = fields
5+
@raw_fields = fields || {}
66
end
77

88
def fields
@@ -21,7 +21,7 @@ def fields_for(type)
2121

2222
def parsed_fields
2323
if raw_fields.is_a?(Hash)
24-
raw_fields.inject({}) { |h, (k, v)| h[k.to_sym] = v.map(&:to_sym); h }
24+
raw_fields.each_with_object({}) { |(k, v), h| h[k.to_sym] = v.map(&:to_sym) }
2525
else
2626
{}
2727
end

test/adapter/json_api/belongs_to_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def test_includes_linked_post
5656
end
5757

5858
def test_limiting_linked_post_fields
59-
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:post], fields: { post: [:title] })
59+
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:post], fields: { post: [:title, :comments, :blog, :author] })
6060
expected = [{
6161
id: '42',
6262
type: 'posts',

test/adapter/json_api/collection_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def test_include_multiple_posts
6060
def test_limiting_fields
6161
actual = ActiveModel::SerializableResource.new(
6262
[@first_post, @second_post], adapter: :json_api,
63-
fields: { posts: ['title'] })
63+
fields: { posts: %w(title comments blog author) })
6464
.serializable_hash
6565
expected = [
6666
{

test/adapter/json_api/fields_test.rb

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
require 'test_helper'
2+
3+
module ActiveModel
4+
class Serializer
5+
module Adapter
6+
class JsonApi
7+
class FieldsTest < Minitest::Test
8+
Post = Class.new(::Model)
9+
class PostSerializer < ActiveModel::Serializer
10+
type 'posts'
11+
attributes :title, :body
12+
belongs_to :author
13+
has_many :comments
14+
end
15+
16+
Author = Class.new(::Model)
17+
class AuthorSerializer < ActiveModel::Serializer
18+
type 'authors'
19+
attributes :name, :birthday
20+
end
21+
22+
Comment = Class.new(::Model)
23+
class CommentSerializer < ActiveModel::Serializer
24+
type 'comments'
25+
attributes :body
26+
belongs_to :author
27+
end
28+
29+
def setup
30+
@author = Author.new(id: 1, name: 'Lucas', birthday: '10.01.1990')
31+
@comment1 = Comment.new(id: 7, body: 'cool', author: @author)
32+
@comment2 = Comment.new(id: 12, body: 'awesome', author: @author)
33+
@post = Post.new(id: 1337, title: 'Title 1', body: 'Body 1',
34+
author: @author, comments: [@comment1, @comment2])
35+
@comment1.post = @post
36+
@comment2.post = @post
37+
end
38+
39+
def test_fields_attributes
40+
fields = { posts: [:title] }
41+
hash = serializable(@post, adapter: :json_api, fields: fields).serializable_hash
42+
expected = {
43+
title: 'Title 1'
44+
}
45+
46+
assert_equal(expected, hash[:data][:attributes])
47+
end
48+
49+
def test_fields_relationships
50+
fields = { posts: [:author] }
51+
hash = serializable(@post, adapter: :json_api, fields: fields).serializable_hash
52+
expected = {
53+
author: {
54+
data: {
55+
type: 'authors',
56+
id: '1'
57+
}
58+
}
59+
}
60+
61+
assert_equal(expected, hash[:data][:relationships])
62+
end
63+
64+
def test_fields_included
65+
fields = { posts: [:author], comments: [:body] }
66+
hash = serializable(@post, adapter: :json_api, fields: fields, include: 'comments').serializable_hash
67+
expected = [
68+
{
69+
type: 'comments',
70+
id: '7',
71+
attributes: {
72+
body: 'cool'
73+
}
74+
}, {
75+
type: 'comments',
76+
id: '12',
77+
attributes: {
78+
body: 'awesome'
79+
}
80+
}
81+
]
82+
83+
assert_equal(expected, hash[:included])
84+
end
85+
end
86+
end
87+
end
88+
end
89+
end

test/adapter/json_api/has_many_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def test_includes_linked_comments
6868
end
6969

7070
def test_limit_fields_of_linked_comments
71-
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:comments], fields: { comment: [:id] })
71+
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:comments], fields: { comment: [:id, :post, :author] })
7272
expected = [{
7373
id: '1',
7474
type: 'comments',

0 commit comments

Comments
 (0)