Practical Five: Deploying to Heroku

We already pushed an app to Heroku at the start of the course to validate your development environment. This time we’ll go through the process more slowly, and provide you with more details about what’s happening so that you can cope with more challenging situations in the future. For example, you now need to deploy your database and its data to Heroku, which you didn’t need to do before.

The documentation at Heroku covers everything too http://devcenter.heroku.com/. Use the ‘getting started’ pages and you should find all that you need. In particular, as we’re moving our deployment with a database to Heroku, which uses Postgresql instead of sqlite3, we need to look at the details of deploying with Postgres at Heroku to understand how the parts fit together.

Add Postgresql to you application

The gemfile for your application details the gems used in your application, and as we want to use Postgresql for production, we need to include that in the file. Open travelagent/gemfile and add uncomment the lines below, or add them if required:

group :development, :test do
  gem 'sqlite3', '1.3.11'
  gem 'byebug', platform: :mri
end

group :production do
  gem 'pg'
end

and, comment out any reference to sqlite3 in the main body of the Gemfile. Then copy the gem ‘sqlite3’ line and move it to the ‘group: development and test’ section next to the line about the ‘byebug’ gem,  then save the file.

You now need to run bundle install to add the gem. This might take a while.

bundle install

Issues installing pg gem

Sometimes this goes smoothly, but other times adding in the pg gem doesn’t go smoothly if you’re trying to also set it up for development. As you’re specifying pg gem is for production, you should find it goes better.  You’ll find notes at the end of the practical for setting up postgresql for development, which can help you debug this process.

If you’re not going to use the pg gem on your machine for development, then you can use the command

bundle install – – without production (that should be a dash dash with no spaces)

This will flag that the gems used for the ‘production’ group should not be installed locally.

If you still find problems with this, then Wikimatze has a another solution, which I’ve found useful. There the author points out options for Mac OS to pass the Postgres library locations to the gem at install, and reminds you on Linux of the other application libraries to install first so the gem install works smoothly.

Set up Heroku account

We’ll deploy to Heroku for the travelagent as it provides free Rails application hosting as well as integration with Git.

If you skipped this previously, then sign up for an account at http://heroku.com and then follow the instructions at https://devcenter.heroku.com/articles/getting-started-with-ruby#set-up. Follow instructions for the ‘standalone installation‘, which is a command line operation. This tends to work smoothly. If you already did all of the first practical, then you will have done this already. We’re just consolidating everything to check that everyone’s at the same place, and knows how to deploy to Heroku as part of your assessment work for the course.

If you don’t have an ssh key in your .ssh directory, then you will need to create one using the details at github. This is done using a terminal, or command prompt.

Upload the ssh key you created for use with Git when prompted. NOTE: when uploading your ssh key supply your heroku account password when prompted for a password.

You will need to supply your public ssh key manually to Heroku in order for this to work. Your ssh keys will be under <youraccount>./ssh then you need to use this command inside aGit bash shell, or terminal after you’ve move to the .sshdirectory:

heroku keys:add id_rsa.pub

It will ask for your email and Heroku password and then upload the file.

You can now create your app on the Heroku server and then upload your app. Be patient during this phase as you are working remotely so give the servers time to respond to your commands.

Use the ‘heroku create’ command inside the travelagent directory to create your app on the server and get its default name. You should see that heroku adds a remote repository to your git repository for remote deployment and tells you what the URL will be.

If the heroku create command doesn’t add your remote repository details, then you can run the command yourself with

git remote add herokugit@heroku.com:your-app-name.git

you can now push the app to heroku with

git push heroku master

Do this now and you’ll see a quick message about adding an RSA host for an IP address …. and then details about writing your objects to the repository and then it will configure the gems it needs to run your Rails application. This may take time, so be patient. When it is done it will launch your application and tell you its deployment URL.

If you go to the URL, you’ll see the ‘We’re sorry, but something went wrong’ message as you’ve not configured the database yet.

We need to tell heroku to create our tables by using these commands:

heroku rake db:migrate

You will probably have a message that some weird database name already exists after the first command, and the second command should show your tables being created. If you now reload the page where your app is, then it should appear there correctly.

Lastly, don’t forget that every time you edit your files, you now need to run ‘git commit -a -m ‘name what you did’ and to then push the files to Heroku with git push heroku master. You need to do this to include your edits in the new commit, or you end up pushing the previous version of your code.

Troubleshooting and Running files on Heroku

If you have the general Rails production error message ‘something went wrong…’ in red, then you can see the log output with the command:

heroku logs

and it will pull down the last twenty or thirty lines of server output and you should see what went wrong. You can also get more lines by using the command ‘heroku logs 200’ which will pull down the last 200 lines of the log. Use this to help debug your applications on Heroku.

Running files to load your database

Once you have your seed files running smoothly to load data into your database, then you can push these to Heroku, and run them there too. As with other commands you add ‘heroku’ to the start of the command so it becomes ‘heroku rake (or rails) <rest of command>’.  We can use this to run the rake script for seeding the database so it becomes

heroku rake ships:seed_cabins

Heroku database limits

Heroku on the free tier allows you up to 10,000 records in your database. These apply to the whole database, and not just one table. This means that if your application has more than than that many of records across various tables, that you need to reduce its size for deployment to this platform. You have a number of options to do this.

If you have only one table, then decide which records are representative of the application – maybe its just the first 6k you need to keep, or maybe you want to take a few from each area depending upon how the data is structured. For example, if there are a million records covering all of Scotland, then you want to make sure you have some from each region so will need to run queries to select the records you want to keep.

If you have tables that are joined by foreign keys, then this becomes a bit more complicated. You have a variety of options. You can de-normalise your data and remove some rows while extending others. You could also remove records in a cascading manner to reduce the amount of data down to manageable proportions while still making sure to leave the whole representative of the overall data available.

Your other option, of course, is to move up to a paid tier of service for the database. You do not need to do this for any assessment work, however.

Beyond the practical – Using Postgresql For Development

Heroku uses Postgresql databases, so if you know that’s what you’ll be deploying to, then ideally you should also use Postgresql for your development too. This can be tricky to set up, but is worth the effort. You can isolate errors due to data by retrieving the data from your deployed database and running it locally to see what’s gone wrong, and you can also build components using the same database knowledge too. If you want to do this, then install Postgresql for your system, and pgAdmin for managing the databases locally. Most importantly, you can connect to your Heroku instance remotely and debug issues there as well by seeing (and manipulating) what’s in the database.

A key part of setting up your instance of pgAdmin to connect with your Heroku database is to find the connection details. On Heroku go to your project there and then switch to the ‘Resources’ tab where you’ll see Heroku-Postgres listed under ‘Add ons’. Click on that and it will take you a ‘Data’ page for your database. Click on the ‘Settings’ tab, and then the ‘Database Credentials’ with its ‘View Credentials’ button to the right. Click that and you’ll see what you need to enter into the pgAdmin tool to make a connection. The key parts will be:

  • host
  • database
  • user
  • password

The URI puts all of these plus the port into a long string, but is not what you need to use, other than to understand how pgAdmin connects to databases.

The main issue with running postgresql for development is that you need to change the gemfile to specify that you need to use pg gem for everything. This is easy enough to do. You run ‘gem install pg’. and you’ll probably see it fail. This is where it now gets harder, but it is possible.

You will probably need to help bundler find the postgresql installation on your platform and therefore need to specify this by way of a specific flag in for the gem installation. The error messages will help guide you here with the syntax.

We now need to update the gemfile to make this work. Change the line above so that you comment out the pg gem in deployment, and uncomment a line to use pg across the app – there is usually one doing this for sqlite3, which you can change to pg instead. Now run ‘bundle update’ to integrate everything and then you’re ready to go.