Preface
This post is an expansion on a demo I gave to the Carthage Computer Science Club, and the notes recorded on that demo.
Some command may not run correctly (specifically gem
and bundle
) if they’re run as a standard user, and may need to be prefaced with sudo
if you’re using OS X or Linux.
Most of the information relayed here can be found in Heroku’s dev center, and more specifically the Getting Started with Ruby on Heroku article (which almost all of the content here is taken from).
Assumptions
The main assumption here is that you have an existing Sinatra application named app.rb
that you can run by running ruby app.rb
, and that it’s kept in a directory used only for it an related resources, and not just your documents directory.
This also assumes that you’ll use Sequel, a simple database toolkit/ORM for ruby, as your main database interface.
Getting ready to deploy
Before you can deploy to Heroku, you need two things:
- A Heroku account. One can easily be obtained by visiting Heroku’s homepage and clicking Sign up.
- The Heroku Toolbelt. Which can be downloaded at https://toolbelt.heroku.com.
Once you have both a Heroku account, and the Heroku Toolbelt installed, you can run heroku login
in your terminal, where you’ll be prompted for your account information. Once you’ve finished this, the heroku
command line application can manage your applications for you.
Preparing your application to be deployed
Using Git
Heroku deploys using git, a popular version control system. As such, to be able to deploy your application you need to turn it into a git repository.
To do so, navigate to your application’s directory and run the following commands:
git init
. This creates a new git repository in the current directory.git add .
. This tells git that you want to add all files in the current directory, and all files in subdirectories (recursively) to the next commit. A commit is a snapshot of your project at a certain point in time, with a message attached to it.git commit -m "init"
. This makes a new commit to your git repository, with the message “init”. If you want to write a longer message, rungit commit
without the-m "init"
part, which will open your default text editor, just save the file, and close the editor to finish your commit.
Some other configuration files
Heroku also needs you to have two more files: a Procfile
which tells Heroku how to run your application, and a Gemfile
which tells Heroku what gems your project uses.
The Procfile
Your Procfile
is going to be relatively uninteresting, and almost the same as anyone running a Sinatra app on Heroku:
web: bundle exec ruby app.rb -p $PORT
Provided that your application is called app.rb
. Change as needed.
What that says is that you’re going to be running one process, a web
process, and that you want that process to run bundle exec ruby app.rb -p $PORT
, which says run your application on the port Heroku gives you, and run it using the bundle environment you’ve been given.
The Gemfile
Your Gemfile
is going to be somewhat interesting. It tells Heroku what gems need to be installed for your application to run. For a simple Sinatra app that has no dependencies, your Gemfile should look something like this:
source "https://rubygems.org"
# This should be the same as the version of Ruby you have installed locally
ruby "2.0.0"
gem 'sinatra'
Once you have that, you should be able to run bundle install
locally without problem. If you don’t have the bundle
command, you may need to install it using gem install bundler
.
Deploying your application
If you’ve done everything above, you can now send your application to Heroku.
The first thing you need to do is tell Heroku to create a new application for you. You can do that by running
heroku create
NOTE: This requires you to be in a git repository. If you aren’t, you’ve just created a Heroku application without attaching it to a local project, and will have to manually attach it. My suggestion is that you don’t run heroku create
outside of a git repository.
Calling heroku create
will add a new remote location to your git repository so that you can push to Heroku. To do that (which will deploy your code), run
git push heroku master
After Heroku does its thing (specifically installing your gems and running your application), you should be able to visit it. To do that easily, just run heroku open
, which will open your application in your default browser.
If there are any errors, you can read you application’s log by running heroku logs
.
Potential errors with deployment
Because you’re probably attempting to deploy an existing app, you could run into some problems here, especially if you’re using a database. Make sure you’ve included all the gems your using in your Gemfile
, and you’re not using a database right now.
Using a database
Getting a database
Heroku provides a small free PostgreSQL database to all applications if they ask for it. The default database has a row limit on it, but for development it should work fine.
To give your application a PostgreSQL database, you need to run
heroku addons:add heroku-postgresql:dev
This command will output several lines, one of which should look like Attached as HEROKU_POSTGRESQL_RED
. Remember the color you’re given.
Heroku recommends using a DATABASE_URL
variable to store your database’s location, but by default doesn’t promote any database to that config variable. To promote the development database, run heroku pg:promote HEROKU_POSTGRESQL_RED_URL
where RED
is the color given when you added PostgreSQL to your application.
Telling your Sinatra app about the database
To start using Sequel in Sinatra, you need the sinatra-sequel
gem and a database driver. Locally, it’s probably easier to use a sqlite3
database for development.
To get started, you should add the following to your Gemfile
:
gem 'sinatra-sequel'
gem 'sqlite3'
And in you should have database capabilities included in your application now:
require 'sinatra'
require 'sinatra/sequel'
configure do
DB = Sequel.connect('sqlite://database.db')
# DB setup here
end
# Sinatra routing here.
However, if you try to deploy this to Heroku, you’ll have problems. Heroku won’t compile the sqlite3
gem.
To fix this, you need to specify that sqlite3
is only for your development environment, and pg
, the PostgreSQL gem, is only for your production environment. Change your Gemfile
to match:
gem 'sqlite3', :group => 'development'
gem 'pg', :group => 'production'
You’ll also need to start using bundle install --without production
instead of bundle install
now, unless you can install the pg
gem locally (there are occasionally problems).
You’ll also need to change your DB
line to use Heroku’s DATABASE_URL
variable over your sqlite url for the connection. Doing that is fairly easy and takes advantage of overloading:
DB = Sequel.connect(ENV['DATABASE_URL'] || 'sqlite://database.db')
You should now be able to push and have everything go swimmingly at this point.