This gem provides a set of methods which allows you to include, filter and sort an ActiveRecord relation based on a request. It's built to be a simple, robust and scalable system. It follows the JSON:API specification as closely as possible.
It's also an unopinionated solution to help you follow the JSON:API specification. It doesn't care about how you want to handle the results.
Moreover, it integrates seamlessly into your Rails application while not being a full library.
Add this line to your application's Gemfile:
gem'jsonapi-scopes'And then execute:
$ bundleThis gem supports filtering.
The gem add a filter method to define public scopes.
It acts as a regular scope.
classContact < ActiveRecord::BaseincludeJsonapi::Filter# Respond to `apply_filter`filter:first_name,->(value){where(first_name: value)}# Do NOT respond to `apply_filter`scope:last_name,->(value){where(last_name: value)}endYou can use apply_filter in your controller to use the scopes defined with the previous filter method:
classContactsController < ApplicationControllerdefindex@contacts=Contact.apply_filter(params)endendThen you can hit /contacts?filter[first_name]=Bruce to filter contacts where the first name exactly match Bruce.
You can specify multiple matching filter values by passing a comma separated list of values: /contacts?filter[first_name]=Bruce,Peter will returns contacts where the first name exactly match Bruce or Peter.
But /contacts?filter[last_name]=Wayne will be completely ignored.
This gem supports sorting.
The gem add default_sort and sortable_fields methods to control sort options. They can be overridden in controllers.
classContact < ActiveRecord::BaseincludeJsonapi::Sortsortable_fields:lastname,:firstname# List of allowed attributesdefault_sortlastname: :desc,firstname: :asc# default hash with attributes and directionsendYou can use apply_sort in your controller:
classContactsController < ApplicationControllerdefindex@contacts=Contact.apply_sort(params)@contacts=Contact.apply_sort# to only apply default sortendendapply_sort accepts a second parameter to override data set with sortable_fields and default_sort for a specific controller.
classContactsController < ApplicationControllerdefindex@contacts=Contact.apply_sort(params,allowed: :full_name,default: {full_name: :desc})# Or @contacts = Contact.apply_sort(params, allowed: [:lastname, :full_name], default: { full_name: :desc })endendThen you can hit /contacts?sort=lastname to sort contacts by lastname.
Or use negative sort /contacts?sort=-firstname to sort by firstname in desc direction.
You can even combine multiple sort /contacts?sort=lastname,-firstname
This gem supports request include params. It's very useful when you need to load related resources on client side.
classPost < ActiveRecord::BaseincludeJsonapi::Includehas_many:commentsbelongs_to:authorallowed_includes'comments','author.posts'# List of allowed includesendYou can use apply_include in your controller:
classPostsController < ApplicationControllerdefindex@posts=Post.apply_include(params)endendapply_include accepts a second parameter to override data set with allowed_includes for a specific controller.
classPostsController < ApplicationControllerdefindex@posts=Post.apply_include(params,allowed: 'comments')# to allow only comments.# Or @posts = Post.apply_include(params, allowed: ['comments', 'author'])endendThen you can hit /posts?include=comments. You can even combine multiple includes like /posts?include=comments,author.
The gem only handle include on the ActiveRecord level. If you want to serialize the data, you must do it in your controller.
You can load nested relationships using the dot . notation:
/posts?include=author.posts.
Jsonapi::scope raises a Jsonapi::InvalidAttributeError you can rescue_from in your ApplicationController.
If you want to follow the specification, you must respond with a 400 Bad Request.
classApplicationController < ActionController::Baserescue_fromJsonapi::InvalidAttributeError,with: :json_api_bad_requestprivatedefjson_api_bad_request(exception)renderjson: {error: exception.message},status: :bad_requestendendDo not hesitate to contribute to the project by adapting or adding features ! Bug reports or pull requests are welcome.
Inspired by:
The gem is available as open source under the terms of the MIT License.