Basic Reads
Here’s the full code for a JSONAPI endpoint that supports sorting, pagination, sparse fieldsets and a JSONAPI-compliant response:
Let’s walk through each of these files:
- app/models/post.rb
- Our Model. As Martin Fowler puts it, “An object model of the domain that incorporates both behavior and data.”. In this case we’re using ActiveRecord, though other model patterns can be used. This is the M of MVC.
- config/routes.rb
- Sets up the endpoint
/api/v1/posts
, per Rails Routing.
- Sets up the endpoint
- app/serializers/serializable_post.rb
- Given a
Model
, how do we want to represent that model as JSON? We might want to avoid exposing certain attributes, normalize values, or compute something specific to the view. This is the V of MVC. - We use the excellent jsonapi-rb library for serialization. If you’re familiar with active_model_serializers, this code will look very familiar.
- Given a
- app/resources/post_resource.rb
- A
Resource
holds the logic for querying and persisting ourModel
s based on the JSONAPI request. Learn about Resources here.
- A
- app/controllers/posts_controller.rb
- This is a typical Rails Controller, the C of MVC.
- We’ve added
jsonapi resource: PostResource
to tell our controller to use query and persistence logic defined in our Resource.
All of this leads up to the all-important render_jsonapi
method.
render_jsonapi
This method does two things: builds and resolves the “base scope”, and passes relevant options to the serialization layer.
In other words, this lower-level code would be the equivalent:
- We’ve started with a base scope -
Post.all
- and passed it into our Resource, which will modify the scope based on incoming parameters. - We’ve passed a number of boilerplate options to the underlying jsonapi-rb serialization library.
There are times we want to manually build and resolve the scope prior to
calling render_jsonapi
. The show
action is one example.
The #show
action
Our #show action fetches one specific post by ID, rather than a list of posts. To accomodate this, we manually build and resolve the scope instead of applying the default logic in #render_jsonapi
:
Note the scope: false
option - we’ve already resolved our models, so
we tell render_jsonapi
not to run the scoping logic again.
It’s a common convention in Rails to return a 404
response code from
the show
action when a record is not found. Typically you’d raise and
rescue ActiveRecord::RecordNotFound
…but we want to be agnostic to
the database. Instead:
We’re throwing an exception, and using our error handling library to customize the status code when that particular error is thrown.