Host Your Sinatra App on Heroku
Ol' Blue Eyes

Host Your Sinatra App on Heroku

Have a Sinatra app you just wrote that you're dying to publicly showcase or put to use online? Or perhaps you made one a while ago and have been delaying hosting it on Heroku because of the possible headache the process will be? In either case, you've come to the right place, and the goal of this blog is to get you up and running, hosting your Sinatra app on Heroku in about 30 minutes.

Heroku Setup

  1. You'll need to create a Heroku account
  2. Install Heroku CLI : https://devcenter.heroku.com/articles/getting-started-with-ruby#set-up
  3. Login to to Heroku from Heroku CLI (heroku login)

Your git and Heroku accounts will now be sync.

Additionally, Heroku provides great documentation and a walkthrough on these steps here.

Update Your Database

Unless you built your Sinatra with a Postgres database, Sinatra comes out of the box with Sqlite3 database. Heroku is compatible with the former, not the latter, so if you have a Sqlite3 database, you'll need to switch it to Postgres. Here's how:

Environment.rb

My original file looked like this:

ENV['SINATRA_ENV'] ||= "development"

require 'bundler/setup'
Bundler.require(:default, ENV['SINATRA_ENV'])


ActiveRecord::Base.establish_connection(
  :adapter => "sqlite3",
  :database => "db/#{ENV['SINATRA_ENV']}.sqlite"
)

require_all 'app'

Then I added both a test database and production database with the following code. You can omit the test database if you want:

 require 'bundler/setup'
 Bundler.require

  configure :test do
    ENV['SINATRA_ENV'] ||= "test"
   
    require 'bundler/setup'
    Bundler.require(:default, ENV['SINATRA_ENV'])
   
    ActiveRecord::Base.establish_connection(
     :adapter => "sqlite3",
     :database => "db/#{ENV['SINATRA_ENV']}.sqlite"
    )
   end
 
  configure :development do
  ENV['SINATRA_ENV'] ||= "development
 
  require 'bundler/setup'
  Bundler.require(:default, ENV['SINATRA_ENV'])
 
  ActiveRecord::Base.establish_connection(
   :adapter => "sqlite3",
   :database => "db/#{ENV['SINATRA_ENV']}.sqlite"
  )
 end

 configure :production do
  db = URI.parse(ENV['DATABASE_URL'] || 'postgres:///localhost/mydb')
 
  ActiveRecord::Base.establish_connection(
    :adapter  => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
    :host     => db.host,
    :username => db.user,
    :password => db.password,
    :database => db.path[1..-1],
    :encoding => 'utf8'
  )
 end

require_all 'app'

Initially made all three databases with Postgres, and created test and development databases locally for this. I had several issues when I first tried hosting to Heroku, so I swapped SQLite back in for the test and development DBs. If you want to use postgres for all three, the code in the environment.rb will look like this.

 require 'bundler/setup'
 Bundler.require
 
configure :production, :development, :test do
  db = URI.parse(ENV['DATABASE_URL'] || 'postgres:///localhost/mydb')
 
  ActiveRecord::Base.establish_connection(
    :adapter  => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
    :host     => db.host,
    :username => db.user,
    :password => db.password,
    :database => db.path[1..-1],
    :encoding => 'utf8'
  )
 end

require_all 'app'

You can see both (with comments) in my repo on Github.

Database.yml

If you do not have one already, you'll want to create a database.yml file in your config directory, adding your databases in the following format:

development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000

test:
  adapter: sqlite3
  database: db/test.sqlite3
  pool: 5
  timeout: 5000

production:
  adapter: postgresql
  database: catan
  pool: 5
Friendly Warning
Let me save you a lot of time debugging database migration issues in Heroku

You might see documentation that shows the postgres configuration in the database.yml file to look like this:

#--------------------DO NOT DO THIS---------------#
production:
  adapter: postgresql
  database: catan
  encoding: unicode
  pool: 5
  timeout: 5000
  #username: user
  #password: <%= ENV['DATABASE_PASSWORD'] %>
  #host: <%= ENV['DATABASE_HOST'] %>
#--------------------DO NOT DO THIS---------------#

This will certainly cause you issues. You don't need any of these extra parameters (timeout, username, password, host). Heroku will provide them, and it will cause migration issues if you write them in. Simply omit them and write the production database configuration in three lines like I've illustrated above.

If you do chose to use Postgres for your test and development databases, then you will need to complete all of these params. If you're committing to a public repo, it might be wise to save the username and password to your Postgres database in a .env that is included in your .gitignore??

You'll also want to make sure your username and password for your Postgres database is accurate - don't copy mine and forget to edit it :).

If this is still unclear, the Heroku documentation for changing your database from sqlite3 to Postgres is helpful.

Update Gemfile

At this point, you'll need to add the Postgres gem to your Gemfile (gem 'pg'). If you are keeping SQLite for your development database, then you NEED to group it under development (and test) in your gemfile. If you do not, and have the SQLITE3 gem listed in the main body of your Gemfile, you'll hit an error when you try to push your app to Heroku. Fortunately, Heroku ignores the gems in your test or development group, so tuck SQLite3 there.

source 'https://rubygems.org'

gem 'activerecord', '~> 4.2', '>= 4.2.6', :require => 'active_record'
gem 'bcrypt'
gem "pg", "~> 0.21"
gem 'rake'
gem 'require_all'
gem 'shotgun'
gem 'sinatra'
gem 'sinatra-activerecord', :require => 'sinatra/activerecord'
gem 'thin'

group :test, :development do
  gem "pry"
  #comment out sqlite gem if using postgresql for test and development database
  gem 'sqlite3', '~> 1.3.6'
end

group :test do
  gem 'rspec'
  gem 'capybara'
  gem 'rack-test'
  gem 'database_cleaner'
end

Now is also a good time to run bundle install to see if there are any dependency surprises you need to fix. If you're running Ruby version 2.6.1+ and it's been a while since you've run Sinatra, you should expect to encounter a few issues. I walk through debugging 3 dependency issues in this post.

At this point, I also ran my database migrations locally to ensure they worked and I had successfully configured the database.

Since I had a test database I wanted to configure, I ran

rake db:migrate SINATRA_ENV=test

and then ran

rake db:migrate SINATRA_ENV=development

If all this is working, the bulk of the preparation for getting your app hosted is done. Move on to the next step!

add a Procfile

This is simply done in 2 steps. From your project's directory

touch Procfile

then use

bundle exec rackup config.ru -p $PORT to the Procfile

I want to stress 2 things here. The 1 line of code in the Procfile needs to be absolutely identical to what I've posted here. If there's a typo or even any uneccessary whitespace, it will create an "App-crashed" error in Heroku. Please a make the Procfile file simply that. No file extensions. Just Procfile.

RakeFile

Now that you've added and updated database configurations in your environment.rb, you can clean up your rake file.

Out of the box, your Sinatra might have ENV["SINATRA_ENV"] ||= "development" in the first line of the rake file. This now redundant if we are using require_relative './config/environment'. The entirety of your Rakefile can now look like this:

require_relative './config/environment'
require 'sinatra/activerecord/rake'

task :console do
    Pry.start
end

(if you debug with Tux instead of Pry, go ahead and substitute Tux in the code above :)

STOP
before you go any further, run:
`rackup config.ru`
in your terminal

If your app executes fine without any issue, you can proceed to the actual deployment steps for Heroku below. If your app breaks, I strongly encourage you to stop here, debug, and get everything running smoothly. Having the slightest thing off can disrupt the deployment or break the app when you run it in Heroku, so confirm your app performs as expected before moving forward.

Deploy to Heroku

If your migrations worked successfully, and your app boots up successfully and renders in localhost on your machine (using shotgun), then it's time to deploy to Heroku.

This is also a simple 2 step process. After committing and pushing your most recent project changes to Github:

heroku apps:create <name_of_your_app>

then

git push heroku master

At this point, Heroku should create an app of your naming, and then you'll push your most recently committed version of your app to Heroku.

Simple enough.

Before you go any further, let me stop you. At this point, I had some issues with creating a database migration and breaking Heroku, so let me share a few things here.

Run

heroku addons

This should return the following:

No alt text provided for this image

This shows Heroku has already established a Postgres Database for your app

If you do not see a Postgres database listed, you'll want to run the following command to create one in Heroku:

heroku addons:add heroku-postgresql: plan-name

If your account plan was hobby-dev, like mine above, that is what you'd use as the value for plan name.

With the database created, you can now run a migration. If you've made migrations files in Sinatra already (which I'm assuming you have since this was a project), we can forego creating migrations files and simply migrate:

heroku run rake db:migrate

With that, you should see a successful migration.

No alt text provided for this image

Those beautiful horizontal lines

Using the command heroku open you should see your app open up in a web browser hosted by Heroku. If you see an error at this point, run

heroku restart

and then try running

heroku open

again.

If everything goes well, at this point, you should have a live site!

If you are getting App-crashed errors, check your Procfile and make sure everything is perfect in there, check out this short article, and then Googling.

Documentation

The official Heroku Documentation

Getting started (example of hosting a generic app) on Heroku

Heroku walkthrough hosting Rails5 (which you can follow along as an analogy for Sinatra)

Heroku's statement on SQLite

How to install Postgres (probably the most useful of the Heroku docs for this process)

Blogs discussing Hosting your Sinatra App on Heroku (in Chronological Order)

2013 - The Official Flatiron School blog

2013 - Deploying a Simple Sinatra App with Postgres to Heroku

2013 - Get Started with Sinatra on Heroku

2018 - Deploying Sinatra App to Heroku

2017 - I Deployed My Sinatra App to Heroku

My Project:

Do you like playing Settlers of Catan? I wrote a Sinatra app that keeps in-game stats of the most frequent roles in a game of Catan, providing data that can influence your strategy.

Check it out:

Catan Stats on Heroku

Github repo here

Carla Valdivia

Fullstack Web Developer | Ruby On Rails | Javascript | React

3 年

Hi Trevor! I've found your article while I was having a hard time deploying my Sinatra app to Heroku. I just wanted to thank you so much for all the wisdom and knowledge shared. It helped me so much and my app is finally in production. Thank you. PS: Catan is one of my favorite games too :)

回复
Mona Johnson, MS

Coaching Career Changers in Tech, Climate and Beyond

4 年

Playing Catan online has been such a fun way to stay connected with friends and family. Your app would be very handy!!

回复

要查看或添加评论,请登录

Trevor Tarpinian的更多文章

社区洞察

其他会员也浏览了