Rails as an API with Postgresql and Heroku Deployment

My coding buddy Rocky, ready to help walk you through today’s blog post!

In this post, I will be detailing how I set up my project using Rails as an API-only backend with Postgresql as the database, as well as how to deploy to Heroku. With hours spent debugging errors in setting up Postgresql and deploying Heroku, I hope to save new learners a headache and most importantly, some time. Feel free to follow along in your own editor.

The Project: B.O.B.

Blacked Owned Breweries, or B.O.B., is an idea I came up with when my friends and I went out recently to support local, family owned breweries in our area. After visiting our third brewery and speaking with the lovely owners, I wondered if any of the places in the local area were owned by members of the Black community. Wanting to support those businesses, I did a google search that surprisingly didn’t display a lot of results. I instead found myself reading through articles that highlighted these businesses throughout the country. I decided to plan out and build a directory website with some possible user interaction capabilities to have a one-stop online platform that lists these businesses. My objective with this application is to bring more awareness to the existence of Black owned breweries and their products for others like me who don’t know where to find them, or anyone else who wants to support them.

Initial Set Up

First I made sure I was in the folder I wanted to house my project on my command line. I then started a new Rails app by typing the following:

If you are doing this, write the name of your app instead of ‘bob’. Including “— api” in the above command does three main things:

  • It configures your application to start with a more limited set of middleware than normal. Specifically, it will not include any middleware primarily useful for browser applications (like cookies support) by default.
  • It makes ApplicationController inherit from ActionController::API instead of ActionController::Base. As with middleware, this will leave out any Action Controller modules that provide functionalities primarily used by browser applications.
  • It configures the generators to skip generating views, helpers, and assets when you generate a new resource. This essentially means there is no View layer.
  • It creates routes in your config/routes.rb file. (ex. resources:breweries)
  • Info source: https://guides.rubyonrails.org/api_app.html

Including the second line, “ — database=postgresql” changes your database from sqlite3 to Postgresql. Before you do this, Postgresql has to be installed. I used HomeBrew to install pg…more on this later. Once your app is created, the top half of your Gemfile should look like this:

If you scroll down on your left side to the config folder, open it up and select the file database.yml. You should see something similar to the following:

Anything with sqlite3 should be commented out, and the adapter should be set to ‘postgresql’. Please note that if you follow the Postgresql installation and set up a username and password, you will see that information here as well. For security reasons mine are omitted.

The next step I took was creating my table. I opted to use the rails scaffold command, which takes care of building the model, database migration for that model, the controller, and the views file.

Let’s break this down. The command is ‘rails g(short for generate) scaffold <model name> <column name>:<column datatype>’.

For my application, I want to include the name of the brewery, where it’s located, hours of operation (if any), a contact option, an image, and a link to their website. If you look at your folders to the left, you’ll see that the app directory will now have a new controller file within the controller folder, and a new model file within that respective folder. Scroll down to the db directory — you should see a new file within the migrate folder.

After making sure my table was set up correctly, I migrated the table with the following command:

This is when I ran to my first set of errors.

Postgresql errors:

I received this error in my console after trying to migrate my table. Some research on stack overflow provided some possible reasons for this error.

  1. PG could be running on a separate server, in which case finding the port and killing the PID might help.
  2. PG server is not running.
  3. Bad installation that could have resulted in corrupted files.

After a series (and over an hour) of frustrating attempts to start the server by typing in commands suggested on stackoverflow and github, I realized that my error stemmed from the third reason. I uninstalled PG and reinstalled it using Homebrew this time. After continuing to get the error on my app, I ragequit (read: deleted) my app and restarted it. This time, the database successfully migrated. Onward!

Controller Actions

The advantage of using the scaffold command is that it automatically creates your CRUD methods in the controller file. However, if you are still learning about these methods I recommend writing them manually until you have a solid understanding of how they work and why before using scaffold. It’s better to know what’s going on behind the magic!

For my application, I want to include a form that will allow users to contribute to the directory by adding breweries they may know of in their local areas. For that reason I will need an index, show, create, edit/update, and delete action.

Discussing the controller actions in detail will perhaps be written in another post, but what this does is create a JSON api when the server is ran by typing rails s into your terminal. Since there is no view layer, I have not set up a homepage. Enter the endpoint of your route after the ‘:3000/’ in your server url. If you have not added any data to your database, you can create seed data (db/migrate/seeds.rb) and run rails db:seed to have something to start with.

Deploying to Heroku

At this point I wanted to begin working on the front-end of my project. There will be many more updates to the backend, but at this point I am now able to make an API call to the endpoint and access the information that’s there.

I chose Heroku to host my backend website. I believe users can deploy up to 5 applications for free. As I plan to build the front-end using React with a collaborator (shoutout to John!), we need an online endpoint to access. Here is how I went about doing that:

Create an account. After verifying your account, you will be taken to your dashboard. In the top right corner you will see a button that says “New”. After clicking on it, select “Create App” from the dropdown menu. You will be asked to name your app — this name will be part of the URL . You will then be redirected to another page. Once there, choose how you want to go about submitting your project. I chose to do it via Github.

After authorizing Heroku to access your Github profile, you can type the name of your project repository — given that you’ve created one and pushed your application to it — and Heroku will upload it! Almost there. Scroll down and you should see a button that says “Deploy”. Go ahead and click that. If all goes well, after a few minutes your application should be deployed and able to viewed by clicking on “View” button underneath that section. As for me, that was not the case.

Heroku Errors

As it turns out, Heroku could not deploy my app because it was “not running on a Ruby version supported by Heroku”. My app was using ‘ruby 2.6.1', when the newest version was ‘3.0.1’.

To fix this, I first had to update my rvm (Ruby Version Manager). I did so by running rvm get stable into my terminal. After doing this, I updated my ruby version by running rvm upgrade 3.0.1. Sweet, all set. OR SO I THOUGHT.

This wasn’t enough. I needed to change the ruby version in my Gemfile as well. After doing so, I ran bundle install and committed my changes to Github. I also saved my file. Still, Heroku continued to fail to deploy my app, stating the same error. After many failed attempts, I finally realized…

I updated my Ruby version and Gemfile, ran bundle install, and saved my changes to Github. I ran the following command: ruby -v in my terminal, and there was the root of the problem. My program was still using ‘ruby 2.6.1’. By running rvm default use ruby 3.0.1, my application was finally using the updated version.

With this my application successfully deployed! Now I am able to access the url endpoint when I make my fetch requests with the front-end.

Thank you for reading; I hope this was helpful to anyone learning to use Rails as an api-only backend.

Happy coding.

Software Engineering graduate with a penchant for matcha lattes and baked goods. Most of my content will consist of RoR, JS, HTML/CSS, and React.