Here's an example resource from the example app just to give you a taste of the possibilities.
class EmployeeResource < ApplicationResource attribute :first_name, :string attribute :last_name, :string attribute :age, :integer attribute :created_at, :datetime, writable: false attribute :updated_at, :datetime, writable: false attribute :title, :string, only: [:filterable, :sortable] has_many :positions has_many :tasks many_to_many :teams polymorphic_has_many :notes, as: :notable has_one :current_position, resource: PositionResource do params do |hash| hash[:filter][:current] = true end end filter :title, only: [:eq] do eq do |scope, value| scope.joins(:current_position).merge(Position.where(title: value)) end end sort :title do |scope, value| scope.joins(:current_position).merge(Position.order(title: value)) end sort :department_name, :string do |scope, value| scope.joins(current_position: :department) .merge(Department.order(name: value)) end end
A pretty boilerplate controller that just interfaces with the resource
class EmployeesController < ApplicationController def index employees = EmployeeResource.all(params) respond_with(employees) end def show employee = EmployeeResource.find(params) respond_with(employee) end def create employee = EmployeeResource.build(params) if employee.save render jsonapi: employee, status: 201 else render jsonapi_errors: employee end end def update employee = EmployeeResource.find(params) if employee.update_attributes render jsonapi: employee else render jsonapi_errors: employee end end def destroy employee = EmployeeResource.find(params) if employee.destroy render jsonapi: { meta: {} }, status: 200 else render jsonapi_errors: employee end end end
Now you can query your endpoints simply and powerfully, like:
Request: http://localhost:3000/api/v1/employees?filter[title][eq]=Future Government Administrator&filter[age][lt]=40
JSON-API response
{ "data": [ { "id": "1", "type": "employees", "attributes": { "first_name": "Quinn", "last_name": "Homenick", "age": 36, "created_at": "2025-03-21T23:04:40+00:00", "updated_at": "2025-03-21T23:04:40+00:00" }, "relationships": { "positions": { "links": { "related": "/api/v1/positions?filter[employee_id]=1" }, "data": [ { "type": "positions", "id": "1" }, { "type": "positions", "id": "2" } ] }, "tasks": { "links": { "related": "/api/v1/tasks?filter[employee_id]=1" } }, "teams": { "links": { "related": "/api/v1/teams?filter[employee_id]=1" } }, "notes": { "links": { "related": "/api/v1/notes?filter[notable_id]=1&filter[notable_type][eql]=Employee" } }, "current_position": { "links": { "related": "/api/v1/positions?filter[current]=true&filter[employee_id]=1" }, "data": { "type": "positions", "id": "1" } } } } ], "included": [ { "id": "1", "type": "positions", "attributes": { "title": "Future Government Administrator", "active": true }, "relationships": { "employee": { "links": { "related": "/api/v1/employees/1" } }, "department": { "links": { "related": "/api/v1/departments/3" } } } }, { "id": "2", "type": "positions", "attributes": { "title": "Manufacturing Specialist", "active": false }, "relationships": { "employee": { "links": { "related": "/api/v1/employees/1" } }, "department": { "links": { "related": "/api/v1/departments/2" } } } } ], "meta": {} }