class JsonApiServer::Sort
Description:¶ ↑
Implements sort parameters per JSON API Spec: jsonapi.org/format/#fetching-sorting.
From the spec: βThe sort order for each sort field MUST be ascending unless it is prefixed with a minus (U+002D HYPHEN-MINUS, β-β, in which case it MUST be descending.β
This class (1) whitelists sort params, (2) optionally specifies a default order, and (3) generates a sub-query based on these params.
Usage:¶ ↑
A sort request will look like:
/topics?sort=-created,title
This gets converted to an array. Sort
order is ASC by default. Minus = DESC.
['-created', 'title']
Sort
attributes are configured like so. :permitted
are whitelisted attributes. :default
specifies the default sort order. If a user specifies sort params other than those in :permitted
, a JsonApiServer::BadRequest
exception is raised which renders a 400 error.
{ permitted: [:id, :title, { created: { col_name: :created_at}], default: { id: :desc } }
In this example, id, title and created (alias for created_at column) are permitted sort params.
Example:¶ ↑
# create sort options sort_options = { permitted: [:id, :title, { created: { col_name: :created_at}], default: { id: :desc } } # create instance sort = JsonApiServer::Sort.new(request, Topic, sort_options) # merge into master query recent_topics = Topic.recent.merge(sort.query) # see sort params puts sort.sort
Note:¶ ↑
JsonApiServer::Builder
class provides an easier way to use this class.
Attributes
Model passed in constructor.
(Hash) Sort
options. Specify the attributes that can be used in ActiveRecord query method 'sort'. No sort attributes can be used except for those specified here.
-
permitted
- array of model attribute names -
default
- used if no sort params are specified (or rejected)
i.e.,
Allows sorting on model attributes :id, :title, :created. If no sort params are specified in the request, it sorts by 'id' desc.
{ permitted: [:id, :title, { created: { col_name: :created_at}], default: { id: :desc } }
Request query params (request.query_parameters).
Controller
request object.
Public Class Methods
Params:
- request - instance of request object - options - sort options. See #options documentation.
# File lib/json_api_server/sort.rb, line 92 def initialize(request, model, options = {}) @request = request @model = model @options = options @params = request.query_parameters end
Public Instance Methods
Instance of JsonApiServer::SortConfigs
based on options
.
# File lib/json_api_server/sort.rb, line 120 def configs @configs ||= JsonApiServer::SortConfigs.new(options) end
Returns an ActiveRecord::Relation if sort_params
are present. Otherwise returns nil. Instance is a query fragment intended to be merged into another query.
Example:¶ ↑
sort = JsonApiServer::Sort.new(request, Comment, options) Comment.recent.merge!(sort.query)
# File lib/json_api_server/sort.rb, line 108 def relation @relation ||= model.order(sort_params) if sort_params.present? end
Calculated ActiveRecord 'order' parameters. Use in queries.
# File lib/json_api_server/sort.rb, line 125 def sort_params @sort_params ||= begin attrs = sort.split(',') sort_params = convert(attrs) sort_params.empty? ? configs.default_order : sort_params end end
Protected Instance Methods
Converts to ActiveRecord query order parameters; whitelists based on configs. Raises JsonApiServer::BadRequest
with descriptive message if attribute is not whitelisted.
# File lib/json_api_server/sort.rb, line 138 def convert(attrs) whitelisted = [] attrs.each do |attr| attr.strip! order = attr.start_with?('-') ? :desc : :asc attr_name = order == :desc ? attr.slice(1..attr.length) : attr config = configs.config_for(attr_name) if config.nil? msg = I18n.t('json_api_server.render_400.sort', param: attr_name) raise JsonApiServer::BadRequest, msg end whitelisted << { (config[:col_name] || config[:attr]) => order } end whitelisted end