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": {}
}