1. Getting Started
  2. Application Setup
    1. Gem Setup
    2. Postgresql Gem Support
    3. Database Configuration
      1. With Postgresql in All Environments
      2. With Postgresql in Production Only
    4. Initialize Your Database
    5. Puma Web Server Configuration
    6. Verify Your Tests Still Pass
  3. Heroku Setup
    1. Creating The Heroku Application
    2. Environment Variables
      1. An Aside: Dotenv-Rails
    3. Deploying To Heroku
      1. Advanced
    4. View Your Application Online
  4. Change Bundler Back
  5. Bonus Heroku Add-Ons Worth Using
    1. Papertrail
      1. Full Create Command
  6. Resources

Deploying to Heroku is supposed to be easy, and compared to putting together and managing your own server, it is definitely less complicated, but it is complicated. So, I figured I would put together a post when I set it up for a new application, Running on Rails 5. I have already done this for an app I upgraded from Rails 4 to Rails 5.

1. Getting Started

If you already have a Rails app built, switch into that directory. If not, then come back when you are ready.

2. Application Setup

First, create a new branch. From the root directory of your app, type:

git checkout -b heroku-deployment

2.1. Gem Setup

We need to make sure that the pg, puma, and rails_12factor gems are loaded in the right places in our Gemfile.

If you are using Postgresql only in production, use this:

gem 'puma'

group :production do
  gem 'rails_12factor'
  gem 'pg'
end

If you aren’t using Postgresql in production, use the following:

gem 'puma'

group :production do
  gem 'rails_12factor'
end

2.2. Postgresql Gem Support

If you are on Ubuntu, make sure that you have Postgresql installed:

sudo apt-get install postgresql libpg-dev

And verify the pg gem installs just fine:

gem install pg

Now, set Bundler to install with production gems

bundle install --with production

And check that Rake also runs production just fine

bundle exec rake -P

2.3. Database Configuration

2.3.1. With Postgresql in All Environments

Your config/database.yml file will need the following:

default: &default
  adapter: postgresql
  pool: 5
  timeout: 5000

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default
  url:  <%= ENV['DATABASE_URL'] %>
  pool: <%= ENV['DB_POOL'] || ENV['RAILS_MAX_THREADS'] || 5 %>

2.3.2. With Postgresql in Production Only

Your config/database.yml file will need the following:

default: &default
  adapter: sqlite3
  pool: 5
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

# Warning: The database defined as 'test' will be erased and
# re-generated from your development database when you run 'rake'.
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: db/test.sqlite3

production:
  <<: *default
  url:  <%= ENV['DATABASE_URL'] %>
  pool: <%= ENV['DB_POOL'] || ENV['RAILS_MAX_THREADS'] || 5 %>

2.4. Initialize Your Database

If you haven’t already initialized your database, run the following:

bundle exec rake db:create
bundle exec rake db:migrate

2.5. Puma Web Server Configuration

Make sure that the following is in your config/puma.rb:

workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count

preload_app!

rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'

on_worker_boot do
  # Worker specific setup for Rails 4.1+
  # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
  ActiveRecord::Base.establish_connection
end

Now create a Procfile at the root of your app directory:

web: bundle exec puma -C config/puma.rb

2.6. Verify Your Tests Still Pass

You have made some changes to your app, so it would be wise to check that the tests still pass. If you aren’t sure how to check, new apps can be tested like so:

bundle exec rake test

If you are using RSpec, then the following should work:

bundle exec rake spec

If you are using a different test suite, check the documentation for it. It may also be listed in the Readme.md file.

3. Heroku Setup

Make sure you have the Heroku Toolbelt installed, and then run:

heroku login

and follow the prompts.

3.1. Creating The Heroku Application

Make sure you are in the root directory of your app before running the commands listed below.

Run the following to create an application, set the database to postgresql, and set it to use the Ruby buildpack. It also adds a git remote repository as staging, which we will use to push our app to.

heroku create --buildpack heroku/ruby --addons heroku-postgresql

If you already created your app, the following two commands can be used separately to add postgresql, and set ruby as a buildpack. Either might be needed, or neither, but better safe than sorry.

heroku addons:create heroku-postgresql
heroku buildpacks:set heroku/ruby

3.2. Environment Variables

The Heroku article on Configuration and Config Vars is a great place to reference.

3.2.1. An Aside: Dotenv-Rails

I use dotenv-rails for development and test environments, but I don’t want Rails to load it in production.

In the Gemfile, I have:

group :development, :test do
  gem 'dotenv-rails'
end

And then, in the config/application.rb file, add the following after the Bundler.require(*Rails.groups) line:

Dotenv::Railtie.load if Module.const_defined?('Dotenv') 

Make sure that your app still works as expected in by making sure your tests still pass, as well as that accessing the the rails console in production mode.

bundle exec rake console -e production

You should not receive any errors. If you do, you need to address them before your app will start properly on Heroku.

3.3. Deploying To Heroku

Anytime you want to deploy your application, you must run the following command, or you may face issues when pushing up a non-master branch. This tells git to overwrite whatever is on the remote master branch with what we branch we are on.

git push heroku heroku-deployment:master

This allows us to define what remote we are pushing to, which branch we want to push up, and which branch it should point to on the remote.

3.3.1. Advanced

So, if you were to setup a ‘staging’ remote, and had a ‘feature-branch’ you wanted to deploy to your Heroku app, you would run the following:

git push staging feature-branch:master

And if you had a ‘production’ remote (say, another Heroku app), and wanted to deploy the ‘feature-branch’, you would run:

git push production feature-branch:master

If you want to take this even further, see my Nerdy Heroku Command for Deploys post.

3.4. View Your Application Online

You should now be able to visit the application URL provided to you by Heroku, and see your application

4. Change Bundler Back

We want to make sure that locally, :development and :test are the only groups loaded.

bundle install --without production

5. Bonus Heroku Add-Ons Worth Using

5.1. Papertrail

Papertrail provides a logging service that can be used without cost.

heroku addons:create papertrail:choklad

You can see documentation on how to access the logs.

5.1.1. Full Create Command

If you would like to make this part of the heroku create command, you can substitute the following for the commands in 3.1. Creating The Heroku App.

heroku create
heroku create --buildpack heroku/ruby --addons heroku-postgresql,papertrail:choklad

6. Resources: