Building a Production Ready Rails JSON API

Ruby on Rails has always been a popular backend of choice in the web development
community. It emphasizes the convention over configuration
programming paradigm, taking care of the most common use cases out of the box,
allowing the programmer to get up and running fast and focus on the code that's
unique to their application instead of reinventing the wheel. As web development technologies have evolved over the years with the increased popularity of Javascript frameworks and single-page applications, Rails has become less popular since a lot of the concerns it handles have now been delegated to the front end (such as rendering templates, build systems etc.), leaving people with the impression that Rails provides too much out of the box, and that they're better off finding a lighter framework to use as an API.

While the criticism is valid, Rails is far from dead. With a little configuration, Rails can easily be fitted for use as a JSON API, letting developers continue to reap the many design decisions made by the Rails community and the agile development speed Rails allows.

This course will teach you how to use Rails4 as a JSON API. We will be building a
backend that will provide the functionality for a Medium
clone called Conduit. Note that this course
only goes over how to build the backend in Rails. Once the backend is completed,
you can pair it with our AngularJS course
to get the entire application running.

Prerequisites

We've provided a specification for our API that we will be building. We
recommended that you go over all the endpoints in the specification and play
around with the demo to get a good idea of the application.

This course assumes some basic Rails knowledge. We'll be using JWT tokens with
Devise for authentication, along with
Jbuilder for rendering JSON. We recommend
using PostgreSQL as your database, but since we're using ActiveRecord, you have
the choice of using SQLite, PostgreSQL, MySQL, or any other ActiveRecord
compatible database.

Install Rails

At the time of writing, this course is using version 4.2.6.
Instructions for installing Rails can be found here

The seed repository is a vanilla Rails 4.2.6 app with all of our dependencies that we'll need for our project in the Gemfile. These gems have not been set up or configured in any way, so we'll be going over how to do that throughout the tutorial when we use the gems for the first time.

Run bundle install

This command will install all the dependencies in our Gemfile that are required for our project.

Configuring Routes for the API

Our JSON API will be authenticated using JWT tokens, so we wont need
Rails's CSRF protection to throw an exception when the CSRF token is missing,
we'll instruct Rails to use a null session instead. Since the JWT token must be
added to requests manually using Javascript, we don't need to worry about the
browser automatically sending cookies to our server (since we're not using
cookies for sessions) to forge one of our user's sessions on a different domain.

CSRF is usually checked on non-GET requests, and by default if no CSRF token is
provided Rails will throw an exception, causing our requests to fail. The
:null_session setting will clear out our session variables instead of causing
an exception to be thrown.

Finally, per the API spec we're adhering to, we want our clients to be able to submit their payloads using lowerCamelCase and our responses should be lowerCamelCase as well. Since we'll
be using Jbuilder for rendering JSON responses, we can use an initializer to
configure Jbuilder to output all JSON keys in lowerCamelCase.

Configure Jbuilder to output keys in lowerCamelCase

Create an initializer in config/initializers/jbuilder.rb with the following code:

Jbuilder.key_formatcamelize: :lower

In order to keep using snake_case throughout our app, we'll have to convert
any incoming parameters in our application to snake_case. This can be achieved
by using a before_action filter
in application_controller.rb

Create a filter to convert incoming parameters to snake_case

Create the following private method in application_controller.rb

defunderscore_params!params.deep_transform_keys!(&:underscore)end

Then, use a before_action filter in application_controller.rb to apply the filter
to every request.

before_action:underscore_params!

Changing our parameters to snake_case has a couple advantages, it keeps our code
looking clean and Ruby-ish (instead of having to reference lowerCamelCase
parameters), and it allows us to pass our parameters to model methods like
update_attributes on our models without having to worry about case conversion.

Configure controllers to respond to json requests

Add respond_to :json after the protect_from_forgery line in ApplicationController

This configuration ensures our controllers will respond with the correct MIME type and enables 3rd party controllers in gems (like Devise controllers) to respond using JSON.