Preconfigured setup for building JSON:API endpoints
Preconfigured set of libraries for building JSON:API compliant endpoints, with matchers for writing more declarative JSON:API specs. This library presumes host project is compliant with using
gem 'infinum_json_api_setup'
bundle exec rails generate infinum_json_api_setup:install
The generator will copy the default translations into the host project (config/locales/json_api.en.yml
), where they can be customized.
Create abstract class for your controllers, include common JSON:API request processing behaviour, and configure responders.
module Api
class BaseController < ActionController::API
include InfinumJsonApiSetup::JsonApi::ErrorHandling
include InfinumJsonApiSetup::JsonApi::ContentNegotiation
self.responder = InfinumJsonApiSetup::JsonApi::Responder
respond_to :json_api
end
end
Use jsonapi_parameters to transform incoming JSON:API compliant data into common Rails parameters
def permitted_params
params.from_jsonapi
.require(:user)
.permit(:first_name, :last_name)
end
Use respond_with
to initiate transformation (serialization) of domain objects into HTTP response.
def show
respond_with User.find(params[:id])
end
respond_with
is well integrated with ActiveRecord::Model
interface. Given a compliant object, the method will correctly set a response status and handle object(or error) serialization based on the presence of .errors
. For a successful domain operation, HTTP status will be 200 OK (or 201 in case of create
controller action). Unsuccessful operations will have HTTP status 422 Unprocessable Entity with errors structured according to JSON:API specification.
def create
respond_with User.create(permitted_params)
end
respond_with
also detects usage from a destroy
controller action and responds with HTTP status 204 No Content and an empty body.
def destroy
respond_with User.destroy(params[:id])
end
This section explains the under-the-hood behavior of the library.
InfinumJsonApiSetup::JsonApi::ContentNegotiation
module is designed to integrate server responsibilities of content negotiation protocol described by the JSON:API specification.
InfinumJsonApiSetup::JsonApi::ErrorHandling
module is designed to catch and handle common exceptions that might bubble up when processing a request.
Exception | HTTP status | Bugsnag notification |
---|---|---|
ActionController::ParameterMissing |
400 | |
ActionDispatch::Http::Parameters::ParseError |
400 | |
Jure::UnpermittedSortParameters |
400 | ✅ |
I18n::InvalidLocale |
400 | |
Pundit::NotAuthorizedError |
403 | ✅ |
ActiveRecord::RecordNotFound |
404 | |
PG::Error |
500 |
InfinumJsonApiSetup::JsonApi::ErrorSerializer
is responsible for serializing domain errors according to JSON:API specification.
Library ships with a set of declarative matchers and request/response helpers. To use them in your specs, configure your RSpec setup in the following way which
:request
metadatarequire 'infinum_json_api_setup/rspec'
RSpec.configure do |config|
# Helpers
config.include InfinumJsonApiSetup::Rspec::Helpers::RequestHelper, type: :request
config.include InfinumJsonApiSetup::Rspec::Helpers::ResponseHelper, type: :request
# Schema paths
config.schema_response_root = Rails.application.root.join('path/to/response_schemas')
config.schema_request_root = Rails.application.root.join('path/to/request_schemas')
end
expect(response).to have_empty_data
expect(response).to have_error_pointer('data/attributes/first_name')
expect(response).to have_resource_count_of(3)
expect(response).to include_all_resource_ids(records.map(&:id))
expect(response).to include_all_resource_ids_sorted(records.map(&:id))
expect(response).to include_all_resource_string_ids(records.map(&:id).map(&:to_s))
expect(response).to include_error_detail('name has been taken')
expect(response).to include_related_resource('user', user.id)
JSON:API setup is maintained and sponsored by Infinum
The gem is available as open source under the terms of the MIT License.