Class: JsonApiServer::Sort

Inherits:
Object
  • Object
show all
Defined in:
lib/json_api_server/sort.rb

Overview

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.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request, model, options = {}) ⇒ Sort

Params:

- request - instance of request object
- options - sort options. See #options documentation.


92
93
94
95
96
97
# 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

Instance Attribute Details

#modelObject (readonly)

Model passed in constructor.



66
67
68
# File 'lib/json_api_server/sort.rb', line 66

def model
  @model
end

#optionsObject (readonly)

(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 }
}


84
85
86
# File 'lib/json_api_server/sort.rb', line 84

def options
  @options
end

#paramsObject (readonly)

Request query params (request.query_parameters).



87
88
89
# File 'lib/json_api_server/sort.rb', line 87

def params
  @params
end

#requestObject (readonly)

Controller request object.



63
64
65
# File 'lib/json_api_server/sort.rb', line 63

def request
  @request
end

Instance Method Details

#configsObject

Instance of JsonApiServer::SortConfigs based on #options.



120
121
122
# File 'lib/json_api_server/sort.rb', line 120

def configs
  @configs ||= JsonApiServer::SortConfigs.new(options)
end

#relationObject Also known as: query

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)


108
109
110
# File 'lib/json_api_server/sort.rb', line 108

def relation
  @relation ||= model.order(sort_params) if sort_params.present?
end

#sortObject

Sort query parameter params.



115
116
117
# File 'lib/json_api_server/sort.rb', line 115

def sort
  @sort ||= params[:sort].to_s
end

#sort_paramsObject

Calculated ActiveRecord ‘order’ parameters. Use in queries.



125
126
127
128
129
130
131
# 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