Skip to content

Commit cb67434

Browse files
authored
Merge pull request #2279 from mkon/link-conditions
Support conditions in link statements
2 parents 05e5ba6 + 572f11b commit cb67434

File tree

6 files changed

+57
-4
lines changed

6 files changed

+57
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Breaking changes:
66

77
Features:
8+
- [#2279](https://github.com/rails-api/active_model_serializers/pull/2279) Support condition options in serializer link statements
89

910
Fixes:
1011

docs/general/serializers.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,15 @@ link :other, 'https://example.com/resource'
238238
link(:posts) { link_author_posts_url(object) }
239239
```
240240

241+
Just like attributes, links also support conditions in options
242+
```ruby
243+
link(:secret, if: :internal?) { object.secret_link }
244+
245+
def internal?
246+
instance_options[:context] == :internal
247+
end
248+
```
249+
241250
#### #object
242251

243252
The object being serialized.

lib/active_model/serializer.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Serializer
2222
autoload :Adapter
2323
autoload :Null
2424
autoload :Attribute
25+
autoload :Link
2526
autoload :Association
2627
autoload :Reflection
2728
autoload :BelongsToReflection
@@ -275,9 +276,14 @@ def self.associate(reflection)
275276
# link(:self) { "http://example.com/resource/#{object.id}" }
276277
# @example
277278
# link :resource, "http://example.com/resource"
279+
# @example
280+
# link(:callback, if: :internal?), { "http://example.com/callback" }
278281
#
279-
def self.link(name, value = nil, &block)
280-
_links[name] = block || value
282+
def self.link(name, *args, &block)
283+
options = args.extract_options!
284+
# For compatibility with the use case of passing link directly as string argument
285+
# without block, we are creating a wrapping block
286+
_links[name] = Link.new(name, options, block || ->(_serializer) { args.first })
281287
end
282288

283289
# Set the JSON API meta attribute of a serializer.

lib/active_model/serializer/link.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
require 'active_model/serializer/field'
2+
3+
module ActiveModel
4+
class Serializer
5+
# Holds all the data about a serializer link
6+
#
7+
# @example
8+
# class PostSerializer < ActiveModel::Serializer
9+
# link :callback, if: :internal? do
10+
# object.callback_link
11+
# end
12+
#
13+
# def internal?
14+
# instance_options[:internal] == true
15+
# end
16+
# end
17+
#
18+
class Link < Field
19+
end
20+
end
21+
end

lib/active_model_serializers/adapter/json_api.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ def relationships_for(serializer, requested_associations, include_slice)
482482
# }.reject! {|_,v| v.nil? }
483483
def links_for(serializer)
484484
serializer._links.each_with_object({}) do |(name, value), hash|
485-
result = Link.new(serializer, value).as_json
485+
next if value.excluded?(serializer)
486+
result = Link.new(serializer, value.block).as_json
486487
hash[name] = result if result
487488
end
488489
end

test/adapter/json_api/links_test.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,21 @@ class LinkAuthorSerializer < ActiveModel::Serializer
1717
link :yet_another do
1818
"http://example.com/resource/#{object.id}"
1919
end
20+
link :conditional1, if: -> { instance_truth } do
21+
"http://example.com/conditional1/#{object.id}"
22+
end
23+
link :conditional2, if: :instance_falsey do
24+
"http://example.com/conditional2/#{object.id}"
25+
end
2026
link(:nil) { nil }
27+
28+
def instance_truth
29+
true
30+
end
31+
32+
def instance_falsey
33+
false
34+
end
2135
end
2236

2337
def setup
@@ -85,7 +99,8 @@ def test_resource_links
8599
:"link-authors" => 'http://example.com/link_authors',
86100
resource: 'http://example.com/resource',
87101
posts: 'http://example.com/link_authors/1337/posts',
88-
:"yet-another" => 'http://example.com/resource/1337'
102+
:"yet-another" => 'http://example.com/resource/1337',
103+
conditional1: 'http://example.com/conditional1/1337'
89104
}
90105
assert_equal(expected, hash[:data][:links])
91106
end

0 commit comments

Comments
 (0)