Class: JsonApiServer::Include
- Inherits:
-
Object
- Object
- JsonApiServer::Include
- Defined in:
- lib/json_api_server/include.rb
Overview
Description:
Handles include parameters per JSON API spec jsonapi.org/format/#fetching-includes.
An endpoint may support an include request parameter to allow the client to customize which related resources should be returned.
ie., GET /articles/1?include=comments,comment.author,tags HTTP/1.1
This class (1) whitelists include params, (2) maintains an array of permitted inclusions, and (3) generates a sub-query if eagerloading is configured for inclusions.
Usage:
An inclusion request looks like:
/topics?include=author,comment.author,comments
It is converted to an array of relationships:
['author', 'comment.author', 'comments']
Includes are whitelisted with a configuration that looks like:
{
{'author': -> { includes(:author) }},
{'comments': -> { includes(:comments) }},
'comment.author'
}
In this example, author, comments, and comment.author are allowed includes. If an unsupported include is requested, a JsonApiServer::BadRequest exception is raised which renders a 400 error.
A proc/lambda can be specified to eagerload relationships. Be careful, to date, there is no way to apply limits to :includes.
Example:
permitted = {
{'author': -> { includes(:author) }},
{'comments': -> { includes(:comments) }},
'comment.author'
}
# create instance
include = JsonApiServer::Include.new(request, Topic, permitted)
# merge into master query
recent_topics = Topic.recent.merge(include.query)
# use in serializers
class CommentSerializer < JsonApiServer::ResourceSerializer
def relationships
if relationship?('comment.author') # relationship? is a helper methods in serializers.
#...
end
end
end
Note:
JsonApiServer::Builder class provides an easier way to use this class.
Instance Attribute Summary collapse
-
#model ⇒ Object
readonly
ActiveRecord::Base model passed in constructor.
-
#params ⇒ Object
readonly
Query parameters from #request.
-
#permitted ⇒ Object
readonly
Include configs passed in constructor.
-
#request ⇒ Object
readonly
ActionDispatch::Request passed in constructor.
Instance Method Summary collapse
-
#include_params ⇒ Object
Array of include params from the request.
-
#includes ⇒ Object
Array of whitelisted include params.
-
#initialize(request, model, permitted = []) ⇒ Include
constructor
Arguments:.
-
#relation ⇒ Object
(also: #query)
Returns an ActiveRecord::Relation object (a query fragment).
Constructor Details
#initialize(request, model, permitted = []) ⇒ Include
Arguments:
-
request
- ActionDispatch::Request -
model
(ActiveRecord::Base) - Model to append queries to. -
permitted
(Array) - Permitted inclusions. To eagerload the relationship, pass a proc:
Example:
Eagerloads author, comments, comments -> authors.
[
{'author': -> { includes(:author) }},
{'comments': -> { includes(:comments) }},
{'comments.author': -> {includes(comments: :author) }},
'publisher.addresses'
]
92 93 94 95 96 97 |
# File 'lib/json_api_server/include.rb', line 92 def initialize(request, model, permitted = []) @request = request @model = model @permitted = permitted.is_a?(Array) ? permitted : [] @params = request.query_parameters end |
Instance Attribute Details
#model ⇒ Object (readonly)
ActiveRecord::Base model passed in constructor.
71 72 73 |
# File 'lib/json_api_server/include.rb', line 71 def model @model end |
#params ⇒ Object (readonly)
Query parameters from #request.
68 69 70 |
# File 'lib/json_api_server/include.rb', line 68 def params @params end |
#permitted ⇒ Object (readonly)
Include configs passed in constructor.
74 75 76 |
# File 'lib/json_api_server/include.rb', line 74 def permitted @permitted end |
#request ⇒ Object (readonly)
ActionDispatch::Request passed in constructor.
65 66 67 |
# File 'lib/json_api_server/include.rb', line 65 def request @request end |
Instance Method Details
#include_params ⇒ Object
Array of include params from the request.
Examples
include=comments becomes ['comments']
include=comments.author,tags becomes ['comments.author', 'tags']
116 117 118 119 120 |
# File 'lib/json_api_server/include.rb', line 116 def include_params @include_params ||= begin params[:include].present? ? params[:include].split(',').map!(&:strip) : [] end end |
#includes ⇒ Object
Array of whitelisted include params. Raises JsonApiServer::BadRequest if any #include_params is not whitelisted.
Examples
include=comments becomes ['comments']
include=comments.author,tags becomes ['comments.author', 'tags']
106 107 108 |
# File 'lib/json_api_server/include.rb', line 106 def includes include_params.select { |i| config_for(i).present? } end |
#relation ⇒ Object Also known as: query
Returns an ActiveRecord::Relation object (a query fragment). Returns nil if no eagerloading is configured.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/json_api_server/include.rb', line 124 def relation @relation ||= begin additions = false # TODO: merge! has unexpected results. frag = include_params.reduce(model.all) do |result, inclusion| config = config_for(inclusion) query = config.respond_to?(:keys) ? config.values.first : nil unless query.nil? additions = true result = result.merge(query) end result end additions ? frag : nil end end |