How to Create a Rails Backend API

A step-by-step guide for building a Rails REST API

Jackson Chen
Geek Culture
7 min readJan 29, 2021

--

Photo by Andrew Neel on Unsplash

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.

Crow’s Foot Reference Guide
Crow’s Foot notation reference

In this guide, we will be building a simple API for a library application using the following domain model:

Domain model for our library-api
Domain model for our library-API

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 to rails 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.
app/model/book.rb

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.

app/models/author.rb

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.

app/models/author.rb
app/models/book.rb

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.

db/schema.rb

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.

Routes and Controller Actions Reference

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.

config/routes.rb

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'
config/routes.rb

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.

db/seeds.rb

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.

JSON response from /authors

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.

app/serializer/author_serializer.rb
app/serializer/book_serializer.rb

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.

--

--

Jackson Chen
Geek Culture

Pre-med turned software engineer. Writing about my experiences and what I’ve learned. Let’s connect. https://jacksonchen.dev