ActiveRecord is an amazing (mostly) database-agnostic ORM framework and so it’s a natural choice to use with non-Rails frameworks such as Sinatra. Note that I’ll be using sqlite3 locally but the Heroku Shared Database is a Postgres database so I’ll be setting my environments appropriately.
In this post I’ve assumed that you have a Sinatra app that is working locally and on Heroku.
Getting it working locally
First up you’ll need a few extra gems in your Gemfile, once again note that I’m using different databases in development, test and production environments.
[code language=”ruby”]
source ‘http://rubygems.org’
gem ‘sinatra’
gem ‘activerecord’
gem ‘sinatra-activerecord’ # excellent gem that ports ActiveRecord for Sinatra
group :development, :test do
gem ‘sqlite3’
end
group :production do
gem ‘pg’ # this gem is required to use postgres on Heroku
end
[/code]
Don’t forget that you’ll need to install the gems using bundler.
[code language=”bash”]
bundle install
[/code]
And you will need to “require” the appropriate files in either your app configuration or the main app controller, the choice is yours 🙂
[code language=”ruby”]
require ‘sinatra/activerecord’
[/code]
At this point you need to provide information that tells your app how to connect to the database.
[code language=”ruby”]
configure :development, :test do
set :database, ‘sqlite://development.db’
end
configure :production do
# Database connection
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
[/code]
You can include this information in your Sinatra app file but I suggest putting the information into a separate configuration file. I keep mine in a file ‘/config/environments.rb’. If you do this you’ll have to include it in your Sinatra app file(s).
[code language=”ruby”]
require ‘./config/environments’
[/code]
In order to use migrations (to set up your object model) you’ll need to create a Rakefile with the following code.
[code language=”ruby”]
# require your app file first
require ‘./app’
require ‘sinatra/activerecord/rake’
[/code]
At this point you can use the typical ActiveRecord Migration syntax to create you migration files, for example:
[code language=”bash”]
rake db:create_migration NAME=create_foos
[/code]
This creates a migration file in ‘./db/migrate’ and this file will be used to create your database table on migration. You will also need to create a class that is the “bridge” between your app and the database table.
[code language=”ruby”]
class CreateFoos < ActiveRecord::Migration
def self.up
create_table :foos do |t|
t.string :name
end
end
def self.down
drop_table :foos
end
end
[/code]
As with the database environment details this code can be included in your main app class but you should put it into it’s own file and include that in your app instead. Once you’ve done this you can run the following to create the database tables – this is only a local operation for now.
[code language=”bash”]
rake db:migrate
[/code]
At this point you should have a local table and method to apply any CRUD action to said table.
And now for Heroku
Before pushing your new app to heroku you’ll need to add the Shared Database addon.
[code language=”bash”]
heroku addons:add shared-database
[/code]
Commit and push your code to Heroku after which you’ll need to rake the remote database.
[code language=”bash”]
heroku rake db:migrate
[/code]
And that’s it. You now have a ActiveRecord working locally and remotely and can develop in a consist way. Aw yeah.
Wes, curious why you choose to use sqllite on your local machine instead of postgres if you know this is going to end up on heroku?
Ease of use really. I have run Postgres locally but it has a number of dependencies and eats my local resources like a little database monster. Sqlite just requires the gem inclusion and I don’t notice the resource usage.
Awesome writeup.
I ran into a wall running heroku rake db:migrate:
PGError: ERROR: invalid value for parameter “client_min_messages”: “”
I ultimately fixed this by switching to the Heroku cedar stack:
heroku create your app –stack cedar
Below is further discussion but the solutions did not work for me:
http://stackoverflow.com/questions/8775406/sinatra-app-on-heroku-activerecordstatementinvalid-pgerror-error
https://github.com/rails/rails/commit/92a3c487bb0d125c437e53a7f45c31fcca97f2d9
Thanks very much! Most of my work is on the cedar stack at the moment including the work behind this post. Are you saying you got that error after running through my steps?
I found I needed an extra ‘/’ before it would create the sqlite…. set :database, ‘sqlite3:///foo.db’