So you've got your hands on some sexy data and you are dying to share it with the world. You've decided to build an API but you are just getting familiar with building an app on Ruby on Rails.
Have you bit off more than you can chew?
NOPE! You can absolutely build an API with basic knowledge of Ruby on Rails.
This tutorial will teach you to configure Rails to work as an API.
Prerequisite Download
We will be using a free tool called Postman to test our API.
Download Postman.
Goal
Create an API of secret menu items available at your favorite fast food restaurant.
This tutorial will help you to create an API that can:
- INDEX all the instances of secret menu items in your API
- SHOW an instance of a secret menu item
- CREATE an instance of secret menu item
- UPDATE an instance of a secret menu item
- DELETE an instance of a secret menu item
8 Steps to creating and testing API functionality
- Create a new Rails API
- Enable CORS(Cross Origin Resource Sharing)
- Create model, controller, database migration table and route via rails g resource command
- Specify what attributes and datatypes of secret menu item
- Define index, show, create, update, and destroy actions
- Create routes for index, show, create, update, and destroy actions
- Seed data
- Fire up your server & postman to test API functionality
STEP 1: Create a new Rails API
In the directory of your choosing, type the following into your terminal. This command will create a new Rails API named secret_menu_api.
#in your terminal
rails new secret_menu_api --api
Change into secret_menu_api directory and open the API by typing the following into your terminal.
# in your terminal
cd secret_menu_api
code .
STEP 2: Enable CORS(Cross Origin Resource Sharing)
CORS allows others to access your API. To prevent unwanted access to your API, Rails automatically disables CORS. Let's enable CORS so others can get access our delicious data!
In the file explorer of your newly created Rails API, expand the following directories to open cors.rb file.
config>initializers>cors.rb
Then,
- Un-comment lines 8-16(NOTE: line numbers may vary but the corresponding code is pasted below for your reference).
- On line 10, change the code (origins 'example.com') to (origins '*') as shown below.
# in config>initializers>cors.rb
# lines 8-16
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
In your file explorer, scroll all the way down and open Gemfile.
Un-comment line 26, gem 'rack-cors'
# in Gemfile
gem 'rack-cors'
In your terminal, run bundle install.
#in terminal
bundle install
STEP 3: Create model, controller, database migration table and route via rails g resource command.
Command syntax:
rails g resource (singular form of your model name)
# in terminal
rails g resource Secret_menu_item
You will see that this command has created the following files in one swoop!
To help you find these files, the file directory is included in the second line.
a model called secret_menu_item
app>models>secret_menu_item.rba controller called secret_menu_items_controller.rb app>controllers>secret_menu_items_controller.rb
a route called routes.rb
config>routes.rba database migration table called 202042720449_create_secret_menu_items.rb
db>migrate>202042720449_create_secret_menu_items.rb
NOTE:202042720449 is a timestamp that denotes the time and date I have created the migration file. Your file will have a different timestamp.
STEP 4: Specify attributes and datatypes of a secret menu item
Our API is designed to display useful information about secret menu items. We will display this information by setting the following as attributes of a secret menu item:
- name of the secret menu item
- name of the restaurant that offers secret menu item
- menu description
Specify attributes
In your 02042720449_create_secret_menu_items.rb, copy and paste the following:
# in db>migrate>202042720449_create_secret_menu_items.rb
class CreateSecretMenuItems < ActiveRecord::Migration[6.0]
def change
create_table :secret_menu_items do |t|
t.string :menu_name
t.string :restaurant_name
t.string :menu_description
end
end
end
Migrate your table
# in your terminal
rails db:migrate
You should see the following output in your terminal if migration has been successfully completed.
# Message in your terminal
== 20200427020449 CreateSecretMenuItems: migrating ============================
-- create_table(:secret_menu_items)
-> 0.0022s
== 20200427020449 CreateSecretMenuItems: migrated (0.0023s) ===================
In your db directory, open schema.rb.
You will see that this file now displays your data structure.
# in db>schema.rb
ActiveRecord::Schema.define(version: 2020_05_03_161829) do
create_table "secret_menu_items", force: :cascade do |t|
t.string "menu_name"
t.string "restaurant_name"
t.string "menu_description"
end
end
STEP 5: Define index, show, create, update, and destroy actions
These actions enable our API to:
- Index: display all instances of secret menu items in our database
- Show: display an instance of a secret menu item
- Create: create an instance of a secret menu item
- Update: update an instance of an existing secret menu item
- Delete: an instance of an existing secret menu item
These actions are defined in our controller in following manner.
Copy and paste the following in your secret_menu_items_controller.rb.
#in app>controllers>secret_menu_items_controller.rb
class SecretMenuItemsController < ApplicationController
def index
@secretMenuItems = SecretMenuItem.all
render json: @secretMenuItems
end
def show
@secretMenuItem = SecretMenuItem.find(params[:id])
render json: @secretMenuItem
end
def create
@secretMenuItem = SecretMenuItem.create(
menu_name: params[:menu_name],
restaurant_name: params[:restaurant_name],
menu_description: params[:menu_description]
)
render json: @secretMenuItem
end
def update
@secretMenuItem = SecretMenuItem.find(params[:id])
@secretMenuItem.update(
menu_name: params[:menu_name],
restaurant_name: params[:restaurant_name],
menu_description: params[:menu_description]
)
render json: @secretMenuItem
end
def destroy
@secretMenuItems = SecretMenuItem.all
@secretMenuItem = SecretMenuItem.find(params[:id])
@secretMenuItem.destroy
render json: @secretMenuItems
end
end
STEP 6: Create routes for index, show, create, update, and destroy actions
Routes receive HTTP requests from client and forward requests to appropriate actions defined in corresponding controllers. We need the routes to be set up for all of the actions we have defined in our controller. Setting these up is quite easy!
Copy and paste the following in your routes.rb
# in config>routes.rb
Rails.application.routes.draw do
resources :secret_menu_items, only: [:index, :show, :create, :update, :destroy]
end
STEP 7: Seed data
1.Create some instances of our secret menu items in our database.
# in db>seed.rb
menu1 = SecretMenuItem.create(menu_name: "Chipotle Nachos", restaurant_name: "Chipotle", menu_description:"Build a plate of nachos with all of your favorite fixings")
menu2 = SecretMenuItem.create(menu_name: "Starbucks butterbeer Frappuccino", restaurant_name: "Starbucks", menu_description:"Combine three pumps of toffee nut syrup and three pumps of caramel with a Crème Frappuccino base")
menu3 = SecretMenuItem.create(menu_name: "Skittles", restaurant_name: "Jamba Juice", menu_description:"A mixture of lemonade, lime sherbet, frozen yogurt, and strawberries")
2.Seed your data
# in your terminal
rails db:seed
3.Check if you seeded your data correctly
# in your terminal
rails c
# It will pull up a console
2.6.1 :002 >
Type in SecretMenuItem.all to pull all of the instances of secret menu items we just seeded.
# in your terminal
2.6.1 :002 > SecretMenuItem.all
(0.5ms) SELECT sqlite_version(*)
SecretMenuItem Load (0.2ms) SELECT "secret_menu_items".* FROM "secret_menu_items" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<SecretMenuItem id: 1, menu_name: "Chipotle Nachos", restaurant_name: "Chipotle", menu_description: "Build a plate of nachos with all of your favorite ...">, #<SecretMenuItem id: 2, menu_name: "Starbucks butterbeer Frappuccino", restaurant_name: "Starbucks", menu_description: "Combine three pumps of toffee nut syrup and three ...">, #<SecretMenuItem id: 3, menu_name: "Skittles", restaurant_name: "Jamba Juice", menu_description: "A mixture of lemonade, lime sherbet, frozen yogurt...">]>
If you see all of the instances of our secret menu items, our data has been seeded correctly!
STEP 8: Fire up your server & postman to test API functionality
Run the following command in your terminal to run your server.
#in your terminal
rails s
Download and open Postman.
Postman is a useful tool to test our API functionality.
POSTMAN LAYOUT
When you open Postman you will see a gray bar between two buttons(GET and Send).
GET is an HTTP method button. If you click on downward facing arrow, you will see drop down options for other HTTP methods.
We will be using different HTTP methods to test different actions of our API (more on that later!).
To the right of our HTTP method button, you will see a gray bar with a placeholder "Enter request URL". This is where we will enter the URL of our API server.
To the right of the URL bar, you will see a blue send button.
Click on send button after we have set up all the necessary parameters to test our API functionality.
HOW TO TEST INDEX ACTION & INDEX ROUTE
Index enables our API to display all instances of secret menu items in our API.
Index responds to GET requests.
In Postman
1.Set HTTP Method to GET
2.Enter request URL of http://localhost:3000/secret_menu_items
3.Press send
On your screen, you will see an array of objects. Each object is an instance of secret menu items. This means that our index action and route have been set up correctly!
[
{
"id": 1,
"menu_name": "Chipotle Nachos",
"restaurant_name": "Chipotle",
"menu_description": "Build a plate of nachos with all of your favorite fixings."
},
{
"id": 2,
"menu_name": "Starbucks butterbeer Frappuccino",
"restaurant_name": "Starbucks",
"menu_description": "Combine three pumps of toffee nut syrup and three pumps of caramel with a Crème Frappuccino base."
},
{
"id": 3,
"menu_name": "Skittles",
"restaurant_name": "Jamba Juice",
"menu_description": "A mixture of lemonade, lime sherbet, frozen yogurt, and strawberries."
},
]
HOW TO TEST SHOW ACTION AND SHOW ROUTE
Show enables our API to display an instance of secret menu item.
Show responds to GET requests.
In the following example, we will have our API display an instance of our secret menu item with id 1. We will do that by specifying the id number in our URL:
http://localhost:3000/secret_menu_items/
(id number of instance you want to pull up)
In Postman
1.Set HTTP Method to GET
2.Enter request URL of http://localhost:3000/secret_menu_items/1
3.Press send
On your screen, you will see the secret menu item with id:1, Chipotle Nachos show up on your screen. This means that our show action and route have been set up correctly!
{
"id": 1,
"menu_name": "Chipotle Nachos",
"restaurant_name": "Chipotle",
"menu_description": "Build a plate of nachos with all of your favorite fixings."
}
HOW TO TEST CREATE ACTION AND CREATE ROUTE
Create enables API to create a new instance of our secret menu item.
Remember how we created new instances of a secret menu items in our seed.rb?
We are going to create one using Postman!
Create responds to HTTP Method POST.
In Postman
1.Set HTTP Method to POST
2.Enter request URL of http://localhost:3000/secret_menu_items
3.Open Body tab
Right below the row that contains HTTP method, URL bar, and send button, you will see a row of tabs. Click on Body tab. It will display another row of options below. Among these options...
- Click on form-data This will display a table with key and value as columns. Under key column, we will enter attribute names and under value column, we will enter values for corresponding attributes.
Under Key column, copy and paste the following
menu_name
restaurant_name
menu_description
Under Value column, copy and paste the following
Hash Brown McMuffin
McDonald's
An Egg McMuffin with the hash brown right in the center
- Click send
On your screen, you will see our new instance of Hash Brown McMuffin. This means that our create action and route have been set up correctly!
{
"id": 4,
"menu_name": "Hash Brown McMuffin",
"restaurant_name": "McDonald's",
"menu_description": "A traditional Egg McMuffin with the hash brown right in the center"
}
HOW TO TEST UPDATE ACTION AND ROUTE
Update enables our API to update an existing instance of a secret menu item.
Update action responds to HTTP Method PATCH.
Let's say we want to update our Hash Brown McMuffin instance with an entirely different secret menu time.
Hash Brown McMuffin has an id of 4.
We are going to tell Postman that we want to update Hash Brown McMuffin by providing its id in the request URL.
http://localhost:3000/secret_menu_items/4
In postman
1.Set HTTP Method to PATCH
2.Enter request URL of http://localhost:3000/secret_menu_items/4
3.Open Body tab
- Click on form-data In the key value table, update the values.
Your key column should already be filled out with the following from testing our create action and route earlier.
Key
menu_name
restaurant_name
menu_description
Under Value column, copy and paste the following
Peanut butter bacon cheeseburger
Shake Shack
A bacon burger with a side of peanut sauce
- press send
Your screen should display all instances of secret menu items with Peanut butter bacon cheeseburger with instance id 4. This means that our update action and route have been set up correctly!
[
{
"id": 1,
"menu_name": "Chipotle Nachos",
"restaurant_name": "Chipotle",
"menu_description": "Build a plate of nachos with all of your favorite fixings."
},
{
"id": 2,
"menu_name": "Starbucks butterbeer Frappuccino",
"restaurant_name": "Starbucks",
"menu_description": "Combine three pumps of toffee nut syrup and three pumps of caramel with a Crème Frappuccino base"
},
{
"id": 3,
"menu_name": "Skittles",
"restaurant_name": "Jamba Juice",
"menu_description": "A mixture of lemonade, lime sherbet, frozen yogurt, and strawberries"
},
{
"id": 4,
"menu_name": "Peanut butter bacon cheeseburger",
"restaurant_name": "Shake Shack",
"menu_description": "A bacon burger with a side of peanut sauce"
}
]
HOW TO TEST DESTROY ACTION & ROUTE
Destroy enables our API to delete an existing instance of secret menu item.
Destroy action responds to DELETE request.
Let's say we want destroy our Peanut butter bacon cheeseburger instance.
Peanut butter bacon cheeseburger has an id of 4.
We are going to tell Postman that we want to delete Peanut butter bacon cheeseburger by providing its id in the request URL.
http://localhost:3000/secret_menu_items/4
In postman
1.Set HTTP Method to DELETE
2.Enter request URL of http://localhost:3000/secret_menu_items/4
3.Press send
Our screen should display all instances EXCEPT for Peanut butter bacon cheeseburger we just deleted. This means that our Destroy action and route have been established correctly!
[
{
"id": 1,
"menu_name": "Chipotle Nachos",
"restaurant_name": "Chipotle",
"menu_description": "Build a plate of nachos with all of your favorite fixings."
},
{
"id": 2,
"menu_name": "Starbucks butterbeer Frappuccino",
"restaurant_name": "Starbucks",
"menu_description": "Combine three pumps of toffee nut syrup and three pumps of caramel with a Crème Frappuccino base"
},
{
"id": 3,
"menu_name": "Skittles",
"restaurant_name": "Jamba Juice",
"menu_description": "A mixture of lemonade, lime sherbet, frozen yogurt, and strawberries"
}
]
There you have it. With basic knowledge of Ruby on Rails, we were able to configure Rails to work as an API by following these 8 steps:
- Create a new Rails API
- Enable CORS(Cross Origin Resource Sharing)
- Create model, controller, database migration table and route via rails g resource command
- Specify attributes and datatypes of a secret menu item
- Define index, show, create, update, and destroy actions
- Create routes for index, show, create, update, and destroy actions
- Seed data
- Fire up your server & postman to test API functionality
Now, go create your new Rails API and let me know how it goes!
Top comments (36)
The flow of article and the way things are organized is amazing. I would be keeping this one as a reference, when I would writing one myself.
Adding pics of postman for each of the steps u described would have been icing on the cake.
Raj!!
Your comment just made my day. Thank you for your amazing suggestion.
That is totally what I wanted to do as well!!
I am a mark up language novice and I couldn't find resources that teach how to insert screenshots into dev.to blog. If you know how, please let me know. I would LOVE to incorporate your suggestion in my next blog.
Thanks again for a great feedback! :)
Great Article, Lisa!
For adding images to dev.to posts you will have an option to upload images on the edit page.
You will have two image types - Cover (for cover image) and Body images (for the post).
On successful upload you will get markdown and URL for the image - you can use either of them, just copy-paste the markdown
![alt text](url)
or copy URL alone addimg
tag -<img src="url" alt="alt text" />
That's all you need to do for adding images.
P.S. for the cover image you do not need to copy-paste, by default it will be at top of post.
Sai!! Why are you so amazing??
I am so excited to apply your advice on my blog posts.
Thank you so much for all the time and effort you've put into giving me great advice.
Your kind words and encouragement inspires me to continue blogging.
Hope you have a great night. You absolutely deserve it!!
Wow, this has been so helpful, the ease with which you explain things is so amazing.
Hey @johnkibirige005 ! Thank you so much for your kindest message. You made my day!
Thank you Lisa
A great contribution, thank you Lisa, I wonder how to write this as a Microservices architectured solution, I'll be elaborating on this, thank you again
In rails 7 it is 36
gem "rack-cors"
Thank you so much @badasscoder ! Haven't worked with Rails in awhile. Your comment will be so helpful to others who come across this blog. Thank you again! :)
Can we expect new rails blog from you ??
Hi @rajat Shahi!
I actually don't write about rails anymore and switched my focus to Node.js and Elasticsearch. There are so many great bloggers on Dev.to who write about rails so I would check out the resources as you continue your journey! Thank you again for a great compliment. :)
This blog was very simple and very informative. thanks :)
Great post, Lisa, very well organized. Everything worked at first attempt. Few words: thanks.
So glad you found it helpful @stefano Corsi! Thank you for the wonderful comment!
Thanks for the tutorial! I'm seeing a lot of job posts that involve Ruby on Rails and this was a great intro for me. It's really cool seeing how similar all of these languages can be.
You are so welcome @charles Hernandez! I am so glad you found it helpful! :)
Sick tutorial thank you so much! I needed a refresher on Rails as haven't practised it in three years. Your article has really helped me regain my confidence cheers Lisa!
@evie !! Thank you so much for your wonderfully uplifting message. I am so glad my blog was helpful!! :))
Wow, nice article. I didn't know it's so easy to create an API using RoR. It's basically some sort of headless/faceless app since you don't have to create the views.
Thanks for sharing.
You are so welcome and thank you for the kind words k00Lgithub! Your message put a huge smile on my face. :)))
Perfect!
As addition I'd add a note how to secure the API, for example with basic auth: api.rubyonrails.org/classes/Action...