Class: JsonApiServer::Builder
- Inherits:
-
Object
- Object
- JsonApiServer::Builder
- Defined in:
- lib/json_api_server/builder.rb
Overview
This class integrates JSON API features – pagination, sorting, filters, inclusion of related resources, and sparse fieldsets – in one place. It collects data to be used by serializers.
-
It merges JSON API sub-queries (i.e, filters, pagination, sorting, etc.) into a query.
-
It provides convenience methods to requested sparse fields, includes and pagination.
Usage:
The Builder class takes two arguments, (1) the controller request and (2) an initial query (i.e., MyModel.all, MyModel.authorized_to(current_user), etc.).
Add JSON API features appropriate for the request. These methods are chainable. Except for sparse fields, JSON API features are configured; filter, include and sort configurations whitelist attributes/behavior while pagination sets defaults and limits on number of records to return.
-
add_pagination(pagination_options)
- for collections -
add_filter(filter_options)
- for collections -
add_include(include_options)
-
add_sort(sort_options)
- for collections -
add_fields
Once features are added, their corresponding values can be accessed:
-
query
- memoized merged query (merges initial request with sort, pagination, filters, includes sub-queries if any) -
paginator
- Paginator class for pagination links. -
includes
- Array of requested (whitelisted) includes (i.e,['comments', 'comment.author']
) -
sparse_fields
- Hash of type/fields (i.e., => [’title’, ‘body’, ‘author’], ‘people’ => [‘name’])
Example
attr_accessor :pagination_options, :sort_options, :filter_options, :include_options
before_action do |c|
c. = { default_per_page: 10, max_per_page: 60 }
c. = {
permitted: [:character, :location, :published],
default: { id: :desc }
}
c. = [
{ id: { type: 'Integer' } },
{ published: { type: 'Date' } },
:location,
{ book: { wildcard: :both } }
]
c. = [
{'publisher': -> { includes(:publisher) }},
{'comments': -> { includes(:comments) }},
'comment.author'
]
end
# A collection.
def index
builder = JsonApiServer::Builder.new(request, Topic.current)
.add_pagination()
.add_filter()
.add_include()
.add_sort()
.add_fields
serializer = TopicsSerializer.from_builder(builder)
render json: serializer.to_json, status: :ok
end
# A resource.
def show
builder = JsonApiServer::Builder.new(request, Topic.find(params[:id]))
.add_include(['publisher', 'comments', 'comments.includes'])
.add_fields
serializer = TopicSerializer.from_builder(builder)
render json: serializer.to_json, status: :ok
end
Instance Attribute Summary collapse
-
#fields ⇒ Object
readonly
JsonApiServer::Fields instance if #add_fields was called.
-
#filter ⇒ Object
readonly
JsonApiServer::Filter instance if #add_filter was called.
-
#include ⇒ Object
readonly
JsonApiServer::Include instance if #add_include was called.
-
#model ⇒ Object
readonly
ActiveRecord::Base model extracted from initial query passed in constructor.
-
#pagination ⇒ Object
readonly
JsonApiServer::Pagination instance if #add_pagination was called.
-
#request ⇒ Object
readonly
ActionDispatch::Request passed in constructor.
-
#sort ⇒ Object
readonly
JsonApiServer::Sort instance if #add_sort was called.
Instance Method Summary collapse
-
#add_fields ⇒ Object
Creates JsonApiServer::Fields instance based on request.
-
#add_filter(permitted = []) ⇒ Object
Creates JsonApiServer::Filter instance based on request, initial query model and filter configs.
-
#add_include(permitted = []) ⇒ Object
Creates JsonApiServer::Include instance based on request, initial query model and include configs.
-
#add_pagination(**options) ⇒ Object
Creates JsonApiServer::Pagination instance based on request, initial query model and pagination options.
-
#add_sort(**options) ⇒ Object
Creates JsonApiServer::Sort instance based on request, initial query model and sort options.
-
#includes ⇒ Object
(Array or nil) Whitelisted includes.
-
#initialize(request, query) ⇒ Builder
constructor
Arguments: - request - an ActionDispatch::Request - query (ActiveRecord::Relation) - Initial query.
-
#paginator ⇒ Object
JsonApiServer::Paginator instance for collection if #add_pagination was called previously, nil otherwise.
-
#relation ⇒ Object
(also: #query)
Merges pagination, filter, sort, and include sub-queries (if defined) into the initial query.
-
#sparse_fields ⇒ Object
(Hash or nil) Sparse fields.
Constructor Details
#initialize(request, query) ⇒ Builder
Arguments:
-
request - an ActionDispatch::Request
-
query (ActiveRecord::Relation) - Initial query.
102 103 104 105 106 |
# File 'lib/json_api_server/builder.rb', line 102 def initialize(request, query) @request = request @initial_query = query @model = model_from_query(@initial_query) end |
Instance Attribute Details
#fields ⇒ Object (readonly)
JsonApiServer::Fields instance if #add_fields was called. nil otherwise.
85 86 87 |
# File 'lib/json_api_server/builder.rb', line 85 def fields @fields end |
#filter ⇒ Object (readonly)
JsonApiServer::Filter instance if #add_filter was called. nil otherwise.
91 92 93 |
# File 'lib/json_api_server/builder.rb', line 91 def filter @filter end |
#include ⇒ Object (readonly)
JsonApiServer::Include instance if #add_include was called. nil otherwise.
94 95 96 |
# File 'lib/json_api_server/builder.rb', line 94 def include @include end |
#model ⇒ Object (readonly)
ActiveRecord::Base model extracted from initial query passed in constructor.
82 83 84 |
# File 'lib/json_api_server/builder.rb', line 82 def model @model end |
#pagination ⇒ Object (readonly)
JsonApiServer::Pagination instance if #add_pagination was called. nil otherwise.
88 89 90 |
# File 'lib/json_api_server/builder.rb', line 88 def pagination @pagination end |
#request ⇒ Object (readonly)
ActionDispatch::Request passed in constructor.
79 80 81 |
# File 'lib/json_api_server/builder.rb', line 79 def request @request end |
#sort ⇒ Object (readonly)
JsonApiServer::Sort instance if #add_sort was called. nil otherwise.
97 98 99 |
# File 'lib/json_api_server/builder.rb', line 97 def sort @sort end |
Instance Method Details
#add_fields ⇒ Object
Creates JsonApiServer::Fields instance based on request. Instance is available through the #fields attribute.
165 166 167 168 |
# File 'lib/json_api_server/builder.rb', line 165 def add_fields @fields = JsonApiServer::Fields.new(request) self end |
#add_filter(permitted = []) ⇒ Object
Creates JsonApiServer::Filter instance based on request, initial query model and filter configs. Instance is available through the #filter attribute.
-
permitted
- JsonApiServer::Filter configs.
138 139 140 141 |
# File 'lib/json_api_server/builder.rb', line 138 def add_filter(permitted = []) @filter = JsonApiServer::Filter.new(request, model, permitted) self end |
#add_include(permitted = []) ⇒ Object
Creates JsonApiServer::Include instance based on request, initial query model and include configs. Instance is available through the #include attribute.
-
permitted
- JsonApiServer::Include configs.
148 149 150 151 |
# File 'lib/json_api_server/builder.rb', line 148 def add_include(permitted = []) @include = JsonApiServer::Include.new(request, model, permitted) self end |
#add_pagination(**options) ⇒ Object
Creates JsonApiServer::Pagination instance based on request, initial query model and pagination options. Instance is available through the #pagination attribute. For collections only.
-
options
- JsonApiServer::Pagination options.
128 129 130 131 |
# File 'lib/json_api_server/builder.rb', line 128 def add_pagination(**) @pagination = JsonApiServer::Pagination.new(request, model, ) self end |
#add_sort(**options) ⇒ Object
Creates JsonApiServer::Sort instance based on request, initial query model and sort options. Instance is available through the #sort attribute.
-
options
- JsonApiServer::Sort options.
158 159 160 161 |
# File 'lib/json_api_server/builder.rb', line 158 def add_sort(**) @sort = JsonApiServer::Sort.new(request, model, ) self end |
#includes ⇒ Object
(Array or nil) Whitelisted includes. An array of relationships (strings) if #add_include was called previously, nil otherwise. i.e,
['comments', 'comments.author']
180 181 182 |
# File 'lib/json_api_server/builder.rb', line 180 def includes @include.try(:includes) end |
#paginator ⇒ Object
JsonApiServer::Paginator instance for collection if #add_pagination was called previously, nil otherwise.
172 173 174 |
# File 'lib/json_api_server/builder.rb', line 172 def paginator @pagination.try(:paginator_for, relation) end |
#relation ⇒ Object Also known as: query
Merges pagination, filter, sort, and include sub-queries (if defined) into the initial query. Returns an ActiveRecord::Relation object.
110 111 112 113 114 115 116 117 118 119 |
# File 'lib/json_api_server/builder.rb', line 110 def relation @relation ||= begin return @initial_query unless @initial_query.respond_to?(:where) %i[pagination filter include sort].each_with_object(@initial_query) do |method, query| frag = send(method).try(:relation) query.merge!(frag) if frag end end end |
#sparse_fields ⇒ Object
(Hash or nil) Sparse fields. Available if #add_fields was previously called. i.e.,
{'articles => ['title', 'body', 'author'], 'people' => ['name']}
187 188 189 |
# File 'lib/json_api_server/builder.rb', line 187 def sparse_fields @fields.try(:sparse_fields) end |