Skip to content

Commit

Permalink
Support conditions in link statements
Browse files Browse the repository at this point in the history
  • Loading branch information
mkon committed Sep 1, 2018
1 parent f3a19bd commit aef6acb
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Breaking changes:

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

Fixes:

Expand Down
9 changes: 9 additions & 0 deletions docs/general/serializers.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,15 @@ link :other, 'https://example.com/resource'
link(:posts) { link_author_posts_url(object) }
```

Just like attributes, links also support conditions in options
```ruby
link(:secret, if: :internal?) { object.secret_link }

def internal?
instance_options[:context] == :internal
end
```

#### #object

The object being serialized.
Expand Down
10 changes: 8 additions & 2 deletions lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Serializer
autoload :Adapter
autoload :Null
autoload :Attribute
autoload :Link
autoload :Association
autoload :Reflection
autoload :SingularReflection
Expand Down Expand Up @@ -275,9 +276,14 @@ def self.associate(reflection)
# link(:self) { "http://example.com/resource/#{object.id}" }
# @example
# link :resource, "http://example.com/resource"
# @example
# link(:callback, if: :internal?), { "http://example.com/callback" }
#
def self.link(name, value = nil, &block)
_links[name] = block || value
def self.link(name, *args, &block)
options = args.extract_options!
# For compatibility with the use cae of passing link directly as string argument
# without block, we are creating a wrapping block
_links[name] = Link.new(name, options, block || ->(_serializer) { args.first })
end

# Set the JSON API meta attribute of a serializer.
Expand Down
21 changes: 21 additions & 0 deletions lib/active_model/serializer/link.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'active_model/serializer/field'

module ActiveModel
class Serializer
# Holds all the data about an serializer link
#
# @example
# class PostSerializer < ActiveModel::Serializer
# link :callback, if: :internal? do
# object.callback_link
# end
#
# def internal?
# instance_options[:internal] == true
# end
# end
#
class Link < Field
end
end
end
4 changes: 4 additions & 0 deletions lib/active_model_serializers/adapter/json_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,10 @@ def relationships_for(serializer, requested_associations, include_slice)
# }.reject! {|_,v| v.nil? }
def links_for(serializer)
serializer._links.each_with_object({}) do |(name, value), hash|
if value.is_a?(ActiveModel::Serializer::Link)
next if value.excluded?(serializer)
value = value.block
end
result = Link.new(serializer, value).as_json
hash[name] = result if result
end
Expand Down
17 changes: 16 additions & 1 deletion test/adapter/json_api/links_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,21 @@ class LinkAuthorSerializer < ActiveModel::Serializer
link :yet_another do
"http://example.com/resource/#{object.id}"
end
link :conditional1, if: -> { instance_truth } do
"http://example.com/conditional1/#{object.id}"
end
link :conditional2, if: :instance_falsey do
"http://example.com/conditional2/#{object.id}"
end
link(:nil) { nil }

def instance_truth
true
end

def instance_falsey
false
end
end

def setup
Expand Down Expand Up @@ -85,7 +99,8 @@ def test_resource_links
:"link-authors" => 'http://example.com/link_authors',
resource: 'http://example.com/resource',
posts: 'http://example.com/link_authors/1337/posts',
:"yet-another" => 'http://example.com/resource/1337'
:"yet-another" => 'http://example.com/resource/1337',
conditional1: 'http://example.com/conditional1/1337'
}
assert_equal(expected, hash[:data][:links])
end
Expand Down

0 comments on commit aef6acb

Please sign in to comment.