Skip to content

Commit 840a787

Browse files
committed
Improve handling for nil relationship links.
1 parent b0a16f3 commit 840a787

File tree

4 files changed

+62
-16
lines changed

4 files changed

+62
-16
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,11 @@ By default the serializer looks for the same name of the attribute on the object
155155
attribute :content do
156156
object.body
157157
end
158-
158+
159159
has_one :comment do
160160
Comment.where(post: object).take!
161161
end
162-
162+
163163
has_many :authors do
164164
Author.where(post: object)
165165
end
@@ -223,6 +223,8 @@ def relationship_related_link(attribute_name)
223223
end
224224
```
225225

226+
If you override `self_link`, `relationship_self_link`, or `relationship_related_link` to return `nil`, the link will be excluded from the serialized object.
227+
226228
## Relationships
227229

228230
You can easily specify relationships with the `has_one` and `has_many` directives.

lib/jsonapi-serializers/serializer.rb

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,14 @@ def relationships
8686
# Merge in data for has_one relationships.
8787
has_one_relationships.each do |attribute_name, object|
8888
formatted_attribute_name = format_name(attribute_name)
89-
data[formatted_attribute_name] = {
90-
'links' => {
91-
'self' => relationship_self_link(attribute_name),
92-
'related' => relationship_related_link(attribute_name),
93-
},
94-
}
89+
90+
data[formatted_attribute_name] = {}
91+
links_self = relationship_self_link(attribute_name)
92+
links_related = relationship_related_link(attribute_name)
93+
data[formatted_attribute_name]['links'] = {} if links_self || links_related
94+
data[formatted_attribute_name]['links']['self'] = links_self if links_self
95+
data[formatted_attribute_name]['links']['related'] = links_related if links_related
96+
9597
if @_include_linkages.include?(formatted_attribute_name)
9698
if object.nil?
9799
# Spec: Resource linkage MUST be represented as one of the following:
@@ -113,12 +115,14 @@ def relationships
113115
# Merge in data for has_many relationships.
114116
has_many_relationships.each do |attribute_name, objects|
115117
formatted_attribute_name = format_name(attribute_name)
116-
data[formatted_attribute_name] = {
117-
'links' => {
118-
'self' => relationship_self_link(attribute_name),
119-
'related' => relationship_related_link(attribute_name),
120-
},
121-
}
118+
119+
data[formatted_attribute_name] = {}
120+
links_self = relationship_self_link(attribute_name)
121+
links_related = relationship_related_link(attribute_name)
122+
data[formatted_attribute_name]['links'] = {} if links_self || links_related
123+
data[formatted_attribute_name]['links']['self'] = links_self if links_self
124+
data[formatted_attribute_name]['links']['related'] = links_related if links_related
125+
122126
# Spec: Resource linkage MUST be represented as one of the following:
123127
# - an empty array ([]) for empty to-many relationships.
124128
# - an array of linkage objects for non-empty to-many relationships.

spec/serializer_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,27 @@ def serialize_primary(object, options = {})
107107
},
108108
})
109109
end
110+
it 'does not include links if relationship_self_link and relationship_related_link are nil' do
111+
post = create(:post)
112+
primary_data = serialize_primary(post, {serializer: MyApp::PostSerializerWithoutLinks})
113+
expect(primary_data).to eq({
114+
'id' => '1',
115+
'type' => 'posts',
116+
'attributes' => {
117+
'title' => 'Title for Post 1',
118+
'long-content' => 'Body for Post 1',
119+
},
120+
'links' => {
121+
'self' => '/posts/1',
122+
},
123+
# This is technically invalid since relationships MUST contain at least one of links,
124+
# data, or meta, but we leave that up to the user.
125+
'relationships' => {
126+
'author' => {},
127+
'long-comments' => {},
128+
},
129+
})
130+
end
110131
end
111132
context 'with linkage includes' do
112133
it 'can serialize primary data for a null to-one relationship' do

spec/support/serializers.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def type
6464

6565
class PostSerializerWithMetadata
6666
include JSONAPI::Serializer
67+
include JSONAPI::Serializer
6768

6869
attribute :title
6970
attribute :long_content do
@@ -83,8 +84,6 @@ def meta
8384
end
8485

8586
class PostSerializerWithContextHandling < SimplestPostSerializer
86-
include JSONAPI::Serializer
87-
8887
attribute :body, if: :show_body?, unless: :hide_body?
8988

9089
def show_body?
@@ -96,6 +95,26 @@ def hide_body?
9695
end
9796
end
9897

98+
class PostSerializerWithoutLinks
99+
include JSONAPI::Serializer
100+
101+
attribute :title
102+
attribute :long_content do
103+
object.body
104+
end
105+
106+
has_one :author
107+
has_many :long_comments
108+
109+
def relationship_self_link(attribute_name)
110+
nil
111+
end
112+
113+
def relationship_related_link(attribute_name)
114+
nil
115+
end
116+
end
117+
99118
class EmptySerializer
100119
include JSONAPI::Serializer
101120
end

0 commit comments

Comments
 (0)