How To Build An API With Ruby On Rails
Tags: ruby, rails
Published: 2020-08-03 16:56:48

Some may feel that using Ruby on Rails as an API is a bit of an overkill. If you are working on a super simple API that may be true but who doesn’t want to take advantage of how easy it is to get up and running with rails. There are many great articles out there on this same subject but I wanted to go a bit further than just creating it and connecting a database.

We will go through the steps to create our API with the database and create some methods to handle some JSON data. For this example, we will call our API ‘my-dope-api’. For this example, I am storing my code on GitHub, and I’ll be using PostgreSQL for the database. Let’s get to it!

**1 - Create The Directory For The Application**

Decide where you want your application files to live then create the directory for it. I will name my directory apiDemo.

```
mkdir apiDemo
```

**2 - Navigate Into That Directory**

```
cd apiDemo
```
**3 - Check Rails Version**
Make sure you are using the latest version.

```
// Check rails version
rails -v

// If you don't have rails install it. 
gem install rails

// If rails is outdated.
gem update rails
```
If you have it installed you should see something like this.
![image shows the current version of Rails on the terminal](https://dev-to-uploads.s3.amazonaws.com/i/cfr9vgewk6y0pv0wdp0e.png)

**4 - Create GitHub Repo**
Go to your GitHub or similar account and create a new repository( I named mine apiDemo) then run the `git clone` command from the directory we just created.

```
git clone git@github.com:yourusername/your-app-name.git
```
**5 - Create The Rails API**
In the same directory run:
```
rails new my-dope-api --api --database=postgresql
```

Let's break this down a bit. The rails `new your-app-name-here` command will create a full application with views and all the bells and whistles we won't be using so we insert the `--api` flag to specify what we want. We follow that with the `--database=` flag which lets us choose our preferred DB system. This will take a few minutes to build out the app for us.
Once Rails has installed all the dependencies, you can open the project in your code editor. I use [VSCode](https://code.visualstudio.com/download). You will notice that Rails has created a bunch of files and directories for us.

![image of file tree on code editor](https://dev-to-uploads.s3.amazonaws.com/i/bc7q9p6b59l0j10vcviy.png)

Inside the `app` directory, we see multiple directories. We will be working on the `controllers` and the `models` directories. First, we'll start by pushing our changes to GitgHub.

```
// Add all changes to staging
git add .

// Commit changes with a message
git commit -m "Initial commit"

// Push changes to your repo
git push origin master
```
**6 - Create A Versioned Directory For Our Controllers**
Like all applications, APIs evolve with time. So to keep things organized we can use simple versioning. Inside the `api` directory, we will create a `v1` directory that will hold our controllers. If we decide to change how our API serves our data we can do so in a new directory named `v2`, then `v3`, etc.

```
// First we create the api directory
mkdir my-dope-api/app/controllers/api

// Followed by the v1 directory
mkdir my-dope-api/app/controllers/api/v1
```

**7 - Generate Controllers**
For this example, we don't need many of the extras included when we generate a controller so I will be using a few flags to help with that. We will create a controller named 'products'. Navigate into the `my-dope-api` directory and run:

```
rails g controller api/v1/products index show --no-helper --no-assets --no-template-engine --no-test-framework
```

This will create our routes and the controller file with stubbed out actions for `index` and `show`. You should see something like this on the terminal:

```
Running via Spring preloader in process 44453
      create  app/controllers/api/v1/products_controller.rb
       route  namespace :api do
  namespace :v1 do
    get 'products/index'
    get 'products/show'
  end
end
```
In your file tree, you should see the new controller.

![image of newly created products controller in the file tree](https://dev-to-uploads.s3.amazonaws.com/i/c82rab9d4a3h8nur4l9v.png)

Inside the `products_controller`, we have some starter code created by the generator.

![image of boilerplate code generated by Rails](https://dev-to-uploads.s3.amazonaws.com/i/tkf69bdw7eeh6y61fj3x.png)

Isn't that just wonderful? Rails is kind enough to write out all the boilerplate code for us. As mentioned earlier, our routes have also been generated but they are not quite correct. 

We want to change them from this:

![image of boilerplate routes generated by rails](https://dev-to-uploads.s3.amazonaws.com/i/s3o3sgf24zolft0damsp.png)

To this:

![image of updated routes including index, create, and show](https://dev-to-uploads.s3.amazonaws.com/i/i1jn02l3kjr5wi4d3rm8.png)

Now, we have working routes for the `index`, `show`, and `create` actions we'll be writing in a minute.

**8 - Generate Models And Migrations**
As we did before, we will use a few flags to avoid any unnecessary boilerplate code.

```
rails g model product name:string brand:string price:string description:string --no-helper --no-assets --no-template-engine --no-test-framework
```
This command will create the migration, the model files, and all the boilerplate code.

![image of the terminal showing the files being created](https://dev-to-uploads.s3.amazonaws.com/i/8450xof35kw20jcg4a5f.png)

![image of code editor showing the contents of the product.rb file](https://dev-to-uploads.s3.amazonaws.com/i/jdr2ep2xcx3105djvxln.png)

![image of code editor showing the contents of the migration file that was just created](https://dev-to-uploads.s3.amazonaws.com/i/p6gvn9ttf1n1i1e9c9db.png)

**9 - Run Postgres**
Since we are using PostgreSQL 11 we have to remember to start our server. Run Postgres then click the start button. Without this step, we will get an error if we try to run a development server on rails.

![image of PostgreSql 11 UI](https://dev-to-uploads.s3.amazonaws.com/i/k6ek9fon28r89xeqffvu.png)

**10 - Create Database And Run Migrations**
Once we have our server running, we can start building and migrating our database with the following commands:

```
// Create the database
rake db:create

// Run the migration files
rake db:migrate
```
You should see something similar to this.

![image of the terminal showing the databases being created and migrations running](https://dev-to-uploads.s3.amazonaws.com/i/zka4x321497sizrbuxkp.png)

**11 - Start Rails Server**
Now we can spin up our Rails app by running rails s on the terminal. If we have done this correctly, we should see a rails welcome screen when we visit localhost:3000 on the browser!

![image of the Rails welcome screen](https://dev-to-uploads.s3.amazonaws.com/i/gy5mx0j9xffllqs2g4sl.png)

Celebrate a bit then push your code. For now, shut down the Rails server by clicking command+c on mac or windows button+c on PC.

**12 - Add Code To The Products Controller**
Now we can put some time into the code that will allow us to persist and read data from our database. Currently, we have a bit of boilerplate code in our controller.

![image of boilerplate routes generated by rails](https://dev-to-uploads.s3.amazonaws.com/i/s3o3sgf24zolft0damsp.png)

The `index` action will display all products and the `show` action will display an individual product based on the id of that product. We will also need a `create` action so we can add data to our database.

Here are all the completed actions in the ProductsController for brevity.

![image of text editor showing contents of the completed code in the Producs_controller file](https://dev-to-uploads.s3.amazonaws.com/i/zz7afq0e7b1sactxgwww.png)

For added security, I like to use Rails [Action Controller Parameters](https://medium.com/r/?url=https%3A%2F%2Fapi.rubyonrails.org%2Fclasses%2FActionController%2FParameters.html%23method-i-require).

>Action Controller Parameters

>Allows you to choose which attributes should be permitted for mass updating and thus prevent accidentally exposing that which shouldn't be exposed. Provides two methods for this purpose: require and permit. The former is used to mark parameters as required. The latter is used to set the parameter as permitted and limit which attributes should be allowed for mass updating.

**13 - Add Test Data**
Ok, let's test this out! We can run `rails c` or `rails console` to start a development environment.

```
// The IRB should look something like this on your terminal:
irb(main):001:0>

// To add a product run:
irb(main):001:0> p = Product.new(name: "PS4", brand: "Sony", price: "$400.00 USD", description: "NextGen Gaming Console")
```
Your output should look like this:

```
=> #<Product id: nil, name: "PS4", brand: "Sony", price: "$400.00 USD", description: "NextGen Gaming Console", created_at: nil, updated_at: nil>
// Since we have a product value assigned to a variable we can call save on our variable and see if it works.
irb(main):002:0> p.save
```
If it saves correctly your output should look like this:

![image of the terminal window displaying the query running on the rails server](https://dev-to-uploads.s3.amazonaws.com/i/4u06p3oqc0ogblejet7f.png)

Now when you call `p` in the IRB you should see that our first product now has an id.

```
irb(main):003:0> p
=> #<Product id: 1, name: "PS4", brand: "Sony", price: "$400.00 USD", description: "NextGen Gaming Console", created_at: "2020-08-03 00:00:34", updated_at: "2020-08-03 00:00:34">
```

Woohooo!! That's working! Now exit the `irb` by typing `exit` into your terminal. Don't forget to push your code!

**14 - Add Seed Data**
Now that we have confirmed our database is working, we can start adding data. I like to have a seeds file so I can have dummy data to play around with when deploying. In the `db` directory, Rails includes a `seeds.rb` file which we will use to add (you guessed it!) our seed data.

![image shows the updated contents of the seeds.rb file](https://dev-to-uploads.s3.amazonaws.com/i/r6vdqq6js1egsd3ggldb.png)
Now we just need to run the command `rake db:seed` and then run our Rails server again.

```
// Run the Rails server
rails s

// Open a browser window and go to 
http://localhost:3000/api/v1/products/
```

You should be able to see all the products we just added.

![image shows our JSON formatted data on the browser](https://dev-to-uploads.s3.amazonaws.com/i/1j7ywkjm4cdpocc237kd.png)

Congratulations! You have just created an API that serves JSON formatted data. From here there are near-infinite possibilities of what you can do with your API. I'd love to hear what you do in the comments. I hope this was helpful and informative. Stay healthy, stay curious!