Deploying a Simple Sinatra App with Postgres to Heroku
I haven’t thought about Sinatra in years—not since using it as a stepping stone to Rails way back when. Then this week I was tasked to design a simple marketing site with a database that could possibly be expanded to include more functionality. Rather than solve this problem with a wrecking ball (Rails), I decided to build it with Sinatra, which we could then expand as need and easily migrate to Rails if required.
Only one problem…how do I use Sinatra, again?
Setting Up A Sinatra App
Well, the good news is that Sinatra has a super simple basic configuration.
First, make sure you have the Sinatra gem installed:
gem install sinatra
Next, create and navigate to your desired project folder and create a Ruby file. Name it whatever you want, but let’s call it app.rb for this example. This is where all of our routing will live.
Open up app.rb and, at the top, put require "sinatra". This will allow us to use Sinatra’s routing DSL and make an easy index route, like so:
# app.rbrequire "sinatra"get "/" do
"Hello world!"
end
Head over to Terminal and start your app by typing ruby app.rb and violà! Your Sinatra app will be visible in your browser at localhost:4567.
Creating an Index View in Sinatra
Obviously you don’t want to display just “Hello world!” so let’s create an HTML file to show, instead.
Create a folder named views/ in the root of your app and add the file index.erb to it. Then open up index.erb and start building a page.
<!doctype html>
<html>
<head>
<!-- Style and javascript links -->
</head>
<body>
<!-- Your content here! -->
</body>
</html>In order to render that file, you’ll have to include it in your index route like so:
# app.rbrequire "sinatra"get "/" do
erb :index
end
Refresh the page and your new HTML should be visible!
Deploying Sinatra to Heroku
Sure, our app doesn’t really do anything, but both extending Sinatra and deploying to Heroku will require similar modifications so let’s get the Heroku configuration out of the way.
First, Heroku will require a config.ru to contain instructions to boot the application. (.ru is the conventional file extension for rackup). So create that file in the root of your application, and add the following lines:
# config.rurequire "./app"
run App
The first line requires your application file app.rb , while the second line starts the application. However, in order to make it work, we’re going to have to wrap our routes in a class named App (or whatever you’d like). So lets’s go back to app.rb and wrap our route like so:
# app.rbclass App < Sinatra::Base
get "/" do
"Hello world!"
end
end
(This will allow you to run rackup in Terminal to start your application, if you’d like. It will default to port 9292, but you can customize the port by passing the -p option like so: rackup -p 4567, which will run the server on port 4567.)
Second, Heroku requires a Gemfile and Gemfile.lock. For this, we’ll need to use the Bundler gem, so make sure you have it installed with gem install bundler. Then, create a file named Gemfile in the root of your app, and add the following:
# Gemfilesource "https://rubygems.org"
gem "sinatra"
You can then run bundle install from your app’s directory to install your gems and created a Gemfile.lock.
With those configurations, your app is ready to be deployed to Heroku! Just create a new app, add the appropriate remote, and push!
Adding Postgres to Sinatra
Setting up Postgres takes a few more steps than with Rails, but we’ll manage. First things first: create a config/directory in the root of your application and add a database.yml file to it.
(In the following configuration, I’ve chosen to use sqlite for my local database, but feel free to create a local Postgres db if you’d like.)
development:
adapter: postgresql
encoding: unicode
database: database_name
pool: 2
username: your_username
password: your_passwordproduction:
adapter: postgresql
encoding: unicode
pool: 5
host: <%= ENV['DATABASE_HOST'] %>
database: <%= ENV['DATABASE_NAME'] %>
username: <%= ENV['DATABASE_USER'] %>
password: <%= ENV['DATABASE_PASSWORD'] %>
Obviously, database_name should change to your actual database name (run createdb database_name to create it), while your_username and your_password should be changed to your username and password for your local machine. The four environmental variables for production will be provided by Heroku’s Postgres add on.
Next, head over to your Gemfile and add a few gems we’ll need to make Postgress work in Sinatra:
# Gemfilesource "https://rubygems.org"
gem "sinatra"# New gems
gem "pg" # for Postgres
gem "rake" # so we can run Rake tasks
gem "sinatra-activerecord" # for Active Record models
To finish configuring Rake, create a file named Rakefile in the root of your app and require Active Record and your app file:
# Rakefilerequire 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
require './app'
To finish configuring Active Record, open app.rb and require it there as well:
# app.rbrequire "sinatra"
require 'sinatra/activerecord'class App < Sinatra::Base
...
end
(Remember to restart your server after making changes!)
Finally, to create database migrations, use the rake command in terminal like so:
rake db:create_migration NAME=create_table_name
Where table_name is the name of the table you’d like to create. Then write your migration as you would in Rails:
class CreateTableName < ActiveRecord::Migration
def change
create_table :table_name do |t|
t.string :name, null: false, default: ""
t.timestamps, null: false
end
add_index :resources, :name, unique: true
end
end(Again, with table_name being your actual table name.)
Then run rake db:migrate in Terminal to run your migrations.
Bonus: Using Sass and Javascript with Sinatra
Both your styles and scripts should live in the public/ directory of your application.
It’s pretty simple for JavaScript—just create the public/javascripts/ directory, place your scripts there, and include them in your HTML <head> with <script type=”text/javascript” src=”javascripts/my_script.js”></script>.
Configuring Sass takes a bit more effort. First, create a similar directory for your Sass files: public/stylesheets/sass.
Then, add the Sass gem to your Gemfile:
# Gemfile...gem "sass"
Next, in your config.ru, make sure your application compiles your Sass as you go:
# config.ru
require 'sass/plugin/rack'...Sass::Plugin.options[:style] = :compressed
use Sass::Plugin::Rack
This will result in your application compiling your Sass files into normal CSS in the public/stylesheets/ directory, which you should link in your HTML like so: <link rel=”stylesheet” type=”text/css” href=”stylesheets/my_styles.css”>.
Sources
The great sinatrarb.com.
Heroku’s article on rack-based apps.
This Jan David article.
And, as always, some random person on StackOverflow.
