How to Create a Rails Backend API
A step-by-step guide for building a Rails REST API
Are you starting a new project and need a dedicated backend API to persist data? Look no further; this guide should lead you in the right direction.
0. Planning out Domain Model and Associations
When starting a new project, it is always important to plan out your domain model and associations first. Refer to the following chart for drawing out your model associations.
In this guide, we will be building a simple API for a library application using the following domain model:
The association between the two models is drawn out above using the “Crow’s Foot” notation.
An author has_many
books. A book belongs_to
an author.
1. Initializing Rails API
In your terminal, use the following command below to initialize a new Rails API.
Template:
$ rails new <API NAME> --api --database=postgresql
Example:
$ rails new library-api --api --database=postgresql
The --api
flag tells Rails to initialize a new application without the bloat and middleware that is not necessary in an API application.
The --database=
flag specifies to Rails what database we will be using. In this case, we will be using PostgreSQL as it is Heroku’s standard database if you plan on deploying your API onto Heroku.
Without specifying a database type, Rails will use SQLite by default.
Remember to change the directory into the root folder of your newly initialized API and run $ bundle
to install your dependencies.
2. Models
Once Rails finishes initializing our API, use the following command to generate our models for our API and tables for our database.
Template:
$ rails generate model <MODEL NAME> <COLUMNS>
Generating the Author Model
In our example, we created a model and migration for our Author table consisting of two columns (name and bio) with type string.
Example:
$ rails generate model Author name:string bio:string
We can shorten the generate command by using the following rules:
- If the column type is a string, we can omit
:string
as Rails will set each column type to string by default if not specified. - Shorten
rails generate model
torails g model
.
Example (shortened):
$ rails g model Author name bio
Generating the Book Model
Based on our domain model, an Author has many Books and a Book belongs to an Author. In order for our database to acknowledge the association between Book and Author, we can add a new column using the name of the model we’re trying to link to and set the column type to :belongs_to
.
Example:
$ rails g model Book title pages:integer author:belongs_to
Setting the column type as :belongs_to
will tell Rails to automatically:
- Create an
author_id
column in the Book table that will store the Author’s ID as a foreign key. - Add the
belongs_to
association to the Book model.
Add Associations to Models
Although Rails may have already set up the association between Book to Author during the Book model generation, we still need to manually set up the association from our Author to Book model.
In our app/models/author.rb
file, add the association has_many :books
.
Note: When adding a has_many
association, remember to pluralize the model.
Add Validations to Models
To prevent invalid data from being saved to our database, we can set up validators for our models.
3. Starting the Database
In order to start the database, we will need to create the database and migrate our changes to update the schema.
$ rails db:create
$ rails db:migrate
Confirm your migrations have taken place by checking the schema in db/schema.rb
. If you find that you are missing a column in one of your tables, do not manually change the schema.rb
as it can break your app.
Generating a Migration
Missing a column in one of the tables? We can generate a migration to add a column to our table.
Note: Remember to pluralize the table name to match database conventions.
Template:
$ rails g migration add_<COLUMN>_to_<TABLE NAME> <COLUMN>:<TYPE>
Example:
$ rails g migration add_genre_to_books genre:string
After generating your migration, simply run $ rails db:migrate
to migrate any changes.
4. Controllers
Now that we have set up our database, we will need a way for the API to access the data. To do this, we will need to set up controllers.
Generating Controllers
Housing all the methods and actions, our controllers will act as the “control” for our collections as the name implies.
Note: The controller name should be plural as it contains all the methods for the collection.
Template:
$ rails g controller <CONTROLLER NAME>
Example:
$ rails g controller Authors
$ rails g controller Books
Adding Actions to Controllers
After generating our controllers, we need to populate the controllers with actions we would like our API to perform.
Following RESTful architecture and CRUD conventions, we can use the chart above as a reference for common actions we’d like in our API.
Note: This does not limit us from creating our own custom actions. We will just need to do a little bit more configuring in our routes if you decide to add a custom action.
5. Routes
When setting up routes, we are basically setting up the APIs endpoints or URLs that will dispatch a certain action to return a response.
Resource Routing
If we followed the naming conventions that Rails like when setting up our controller actions, we can take advantage of Rails resource routing. Navigate to config/routes.rb
and add resources <CONTROLLER NAME>
to your routes.
Custom Routing
If you added a custom action to your controller and wanted to dispatch that action to a custom route, we can use the following template.
Template:
<HTTP VERB> '<PATH>', to: '<CONTROLLER>#<ACTION>'
Example:
get 'custom/path', to: 'authors#index'
6. Test the API
Now that we have our routes set up, we want to make sure our routes are working properly. However, our database currently does not have any data to send back yet. We need to seed our database first.
Seed Database
Navigate to db/seeds.rb
, add some seed data and run $ rails db:seed
.
Starting the Server
Once your database is seeded, start the server by running $ rails s
in your terminal. By default, your Rails server should start on port 3000. If you want to use a different port, you can add the -p <PORT NUMBER>
flag to specify which port you want your server to run on.
Example:
$ rails s -p 3000
Test Endpoints
Once the server is running, we can check the authors route by navigating to http://localhost:3000/authors
in our browser.
Note: Keep in mind, our browsers are only able to perform GET requests. If you want to test out other requests, I recommend using Postman.
This is great that we are getting a response, but where are the books we seeded? This brings us to our next topic, Serializers.
7. Serializers
Serializers allow us to format our data in a way that is easy for developers like us to use. Perhaps, there are some things we want to omit to send back such as passwords or pointless metadata.
Installation
We will be using the ActiveModelSerializer gem. Navigate to your Gemfile
and add gem 'active_model_serializers'
as a dependency. Then run $ bundle
to install all dependencies.
Generate Serializer
Once ActiveModelSerializer is installed, we are given access to a new generate command.
Template:
rails g serializer <MODEL NAME>
Example:
rails g serializer author
rails g serializer book
Serialize your Data
Navigate to your serializers located in app/serializers
directory and add or remove attributes that you’d want in your JSON response.
Now that you have set up your serializers, start up your server again and check out your API’s JSON responses. That looks clean!
Conclusion
Hopefully, this guide gave you a clear understanding of how to start your own Rails API. Being able to build your own API definitely has it’s perks and opens up a lot of opportunities for awesome project ideas.