Deploy a Rails App to Heroku and Keep Your Data
I have a Rails app that I developed over a week during my time at Lighthouse Labs. I thought I'd deploy the app to Heroku so that I can share it with my friends and potential employers. I had some issues switching over from my Sqlite development database to the production Postgres one. It was a battle, from now on all my Rails apps will be made with Postgres right from the start.
First you need to create a Heroku account. I already had one. Next you need to install the Heroku toolbelt, I also already had that installed. There is a good guide here on how to set it up, Heroku Toolbelt. The toolbelt allows you to issue remote commands directly from your terminal without a remote shell. For the rest of this tutorial all commands have to be run from the root directory for the project.
To get my Rails app ready for deployment I had to make some changes. First I had to add the PG (postgres) gem to the gemfile. I also had to add the rails_12factor gem which is required by Heroku. After changing the gemfile run a "bundle update" in the terminal.
Next I had to modify my config/database.yml file to work with Postgres. Basically I had to change all the Sqlite entries to Postgres and add the database name.
That's all we need in order to deploy the app. Now make sure the changes are pushed to git. We'll use git to push to Heroku. To create the app on Heroku simpy run the following command:
heroku create
You will get some confirmation in the terminal and the app name. Heroku has some bizarre names. My app was called "pacific-shelf-76469". Next we are ready to push using git. Heroku does all the heavy lifting so from the app root folder you just have to run:
git push heroku master
The results are in the screenshot below.
I edited the results for display. Heroku runs the git push, bundle install, and some special Heroku stuff. It also lists the url for the app. In my case its https://pacific-shelf-76469.herokuapp.com. The app should be live now at that url.
Moving the data over is a different story.
I found a great Rails Cast on the subject here, #342 Migrating to PostgreSQL. Ryan Bates who puts on the Rails Casts used a tool called Taps that is supposed to take care of converting Sqlite to Postgres. Unfortunately I was unable to get taps to work on my machine. I encountered the error below and was not able to find a solution.
A little disheartened I tried another technique. This involved creating an Sqlite dump file. The dump file is actually a script of SQL commands. Since Sqlite and Postgres are both SQL databases the same commands will work for both. The file needs a little modification though. I found a great post on how to modify the file here, Port to Postgres. See below for a sample of the dumpfile.
After making the modifications I used the dumpfile to load the data into my local Postgres database. I used the following command:
psql -d manoges_development -W db/sqlite-dump.sql
After testing locally I was ready to push the database to Heroku. First I had wipe the Heroku database using this command:
heroku pg:reset DATABASE --app pacific-shelf-76469
After some trial and error I used this command to copy the local database to Heroku:
pg_dump --no-acl --no-owner -h localhost -U myuser | heroku pg:psql
The data was available on Heroku but it didn't work properly. Also after some poking around I discovered that the local copy also did not work properly. I determined that the dumpfile must have been the culprit. So back to the drawing board.
I tried one more tool called PGloader. It was highly recommended. It does the same thing as I tried to do with the manually edited file. PGloader is available through the Ubuntu package manager via apt-get. To work properly it requires a small script. Here is the one that I used:
I tested locally and it was exactly the same. I guess I did the manual editing properly. At this point I had enough with trying to migrate the data. I decided to translate everything into YAML scripts so Rails can load itself using rake. That way it would work everywhere regardless of database type.
Here is a sample of my movies.yml file:
I also had to modify my db/seeds.rb file to accommodate the yml files. It looks like this:
OK after writing YML files for all my databases and data I am good to go. I had to do another git push to heroku then run some rake commands on the remote machine.
First wipe the remote database:
heroku pg:reset DATABASE --app pacific-shelf-76469
Then run the remote rake commands:
heroku run rake db:create
heroku run rake db:migrate
heroku run rake db:seed
OK after all that the app is good to go. It was tedious to write out all the YML files by hand. The lesson to be learned here is don't mix database types in development vs production. If you plan to deploy your app start out with Postgres or whatever you are going to use in deployment.
Co-Founder @ USLege.ai | Building the only AI-first legislative tracking platform.
8 年Good stuff. Switching between the two is annoying. I've learned my lesson and will hopefully never have to do it again.