Building an API from scratch for a web application might sound challenging for a first-timer. But if you have the fundamental Ruby on Rails knowledge, you might even find it easier than you expected.
What is an API ?
Rails can serve as both the front-end and back-end of a website. It can also be configured specifically to work just as an API. So what is an API? Basically, API(Application Programming Interface) is a way for one system to communicate with other external systems. As perfectly explained on Ruby on Rails guides, when people say they use Rails as an “API”, it means developers are using Rails to build a back-end that is shared between their web application and other native applications. The reason most developer use Rails is that it provides a set of defaults that allows us to get up and running quickly. That is why instead of using Rails to generate view files that communicates with the server through forms and links, many developers are treating their web application as just an API client that responds with JSON. So when we are following principles to build an M-V-C structure (Model-View-Controller), rails is only in charge of our models and controllers.
STEP 1 — CREATE A NEW RAILS APP AS AN API
First and foremost we need set up our new Rails app environment by flagging it as an API. Now on your terminal you can follow the format below.
rails new <your_app_name> --api
Have you noticed the api flag we used to specify this is just an API?
--api #this is the api flag.
You may ask the reason. Remember, we mentioned Rails will only used for our models and controller. Therefore,
--api flag will allow Rails to remove a lot of default features and middleware that will not be needed. Now controllers will inherit from ActionController::API instead of ActionController::Base and generators will not create views.
I am building a comicbook app to list my comicbook collection so let’s start my app setup
rails new comics_geek_backend --api
Also I would like to share a helpful tip I came across while watching project built videos: If you are planning to deploy your app to an environment like Heroku, the best practise is to generate a new rails project using Postgresql as the database.(Make sure to download and run Postgres on your computer.)
rails new comics_geek_backend -- database=postgresql -- api
STEP 2— Configure CORS to allow frontend to make requests
CORS is designed to prevent scripts like fetch() from one origin accessing a resource from a different origin unless that resource specifically states that it expects to share. However, while working on our API, we want to have our Rails server running while trying out s endpoints using fetch(). By using the api flag, the Gemfile was altered to include the rack-cors gem which is commented out initially. So let’s go ahead and uncomment our rack-cours gem in our Gems.
We can now go back to our terminal and run bundle install.
run bundle install
In order to get rack-cors working, once the gem is installed, we need to uncomment the following code in config/initializers/cors.rb file .
Rails provides the cors.rb file specifically for defining our rules for cross-origin HTTP requests.New rails app comes with the string “example.com” . The string after origins specifies which hosts will be allowed to make requests to your API. Now we need to change it to “*” to allow all hosts for our simple Rails API.
STEP 3— Planning Models
Now, let’s plan our Models. For my Comicbook app, I want to build two models. First one is a Comicbook model that belongs_to a :publisher and a Publisher model that has_many :comicbooks with the attributes below:
Comicbook — has a title, number, artist, writer, image_url so we can add covers and a description.
Publisher — has only a name
Now we can start using rails generator to create our models. If you would like to have a cheatsheet to check how you can build a rails generator, you can also check my previous blog here => RUBY ON RAILS GENERATORS: HOW TO GET YOUR APP UP AND RUNNING & START A NEW RAILS PROJECT .
STEP 3 — Generate Models and Create Database
I will go ahead and type the generators below to my terminal. rails will default to string if we don't specify a type for our attributes.
rails g model Publisher name --no-testframeworkrails g model Comicbook title description image_url publisher_id:integer number:integer artist writer --no-testframework
Then we have to run
rails db:create && rails db:migrate
This will create two migrations and two models and with minimal seed data we could even test if everything is working as expected!
STEP 4 — Create Seed Data and Test your associations
Now let’s go to our seeds file db/seeds.rb and create publishers and some comicbooks to start with.
marvel = Publisher.create(name: "Marvel Comics")dc = Publisher.create(name: "DC Comics")image= Publisher.create(name: "Image Comics")Comicbook.create(title: "Amazing Spider-man", number:1 description: "Peter Parker tries to continue a show biz career as Spider-Man, yet J. Jonah Jameson's editorials slamming him as a menace makes it hard to find work.", image_url: "https://images-na.ssl-images-amazon.com/images/S/cmx-images-prod/Item/562/DIG000136._SX360_CLs%7C360,508%7Ccu/cmx-cu-sash-lg.png%7C0,0,361,509%20208,356,152,152_QL80_TTD_.jpg", artist: "Steve Ditko", writer: "Stan Lee" , publisher_id: marvel.id)Comicbook.create(title: "Flash Rebirth", number: 1, description: "Geoff Johns and Ethan Van Sciver, the writer/artist team behind the blockbuster GREEN LANTERN: REBIRTH and THE SINESTRO CORPS WAR, create an explosive, jaw-dropping epic that reintroduces Barry Allen as The Flash in this volume collecting the fast-paced 6-issue miniseries. But how will this greatest of all Flashes find his place in the twenty-first century?", image_url: "https://images-na.ssl-images-amazon.com/images/S/cmx-images-prod/Item/48457/DIG010147_1._SX360_QL80_TTD_.jpg", artist: "Ethan Van Sciver", writer: "Geoff Johns" , publisher_id: dc.id)Comicbook.create(title: "Darkness", number: 1, description: "Coming of Age Introducing mafia hitman Jackie Estacado and the ancient power of the Darkness!Jackie Estacado is assaulted by a host of Angelus warriors who attempt to catch him in a vulnerable state. Their goal is to destroy the Darkness forever.", image_url: "https://images-na.ssl-images-amazon.com/images/S/cmx-images-prod/Item/1166/ICO000034._SX312_CLs%7C312,473%7Ccu/cmx-cu-sash-lg.png%7C0,0,313,474%20160,321,152,152_QL80_TTD_.jpg", artist: "Mark Silvestri", writer: "Mark Silvestri" , publisher_id: image.id)
Now we can test the associations on our rails console by typing
2.6.1 :012 > spiderman = Comicbook.firstComicbook Load (0.5ms) SELECT "comicbooks".* FROM "comicbooks" ORDER BY "comicbooks"."id" ASC LIMIT $1 [["LIMIT", 1]]=> #<Comicbook id: 1, title: "Amazing Spider-man", description: "Peter Parker tries to continue a show biz career a...", image_url: "https://images-na.ssl-images-amazon.com/images/S/c...", publisher_id: 1, number: 1, artist: "Steve Ditko", writer: "Stan Lee", created_at: "2020-10-19 20:51:45", updated_at: "2020-10-19 20:51:45">2.6.1 :013 > spiderman.title=> "Amazing Spider-man"2.6.1 :014 > spiderman.artist=> "Steve Ditko"2.6.1 :015 > spiderman.description=> "Peter Parker tries to continue a show biz career as Spider-Man, yet J. Jonah Jameson's editorials slamming him as a menace makes it hard to find work."
STEP 5— Generate Controllers
We have our migrations and models set so let’s create our controllers.
rails g controller Comicbooks
rails g controller Publishers
We can create all the actions we want. So as an example I would like to build an index action for our app/controllers/comicbooks_controller.rb
class ComicbooksController < ApplicationController
render json: comicbooks
STEP 6 — Create Routes
Ok, we are almost there! Let’s go to config/routes.rb and set up our route for the index action.
class ComicbooksController < ApplicationController
Rails.application.routes.draw do resources :comicbooks, only: [:index]end
STEP 7— Test it!
After we complete rest of the controller actions and related routes we can go ahead and run our rails server by simply typing
rails sand go to
localhost:3000/comicbookson our browser we will be able to see our API in action! Yes we made it!!
As a Flatiron School student, writing this article really helped me to learn and have a systematic approach to set up my Rails Api. I am looking forward to building more complex API’s in the future. Happy coding and please let me know if you have any comments or suggestions!