Setting up MongoDB for Heroku in a Sinatra App

by Hamilton Chapman


I've recently started a new job at Pusher. They provide a hosted API that lets you get up and running with adding realtime functionality to your web or mobile app. It's insanely easy to get setup and if you're wanting to play around with making something realtime then give it a try.

My first project required me to create a simple web app for the team to use in the office. Being most comfortable using Ruby I chose to start off with a Sinatra application.

Part of the app involved storing some data. In the past I'd only ever really used Postgres for my database needs, largely because it's widely supported (by Heroku for a start) and it's easy to grasp how it works. This time, however, I ended up using MongoDB.

Mongo is the NoSQL database. Instead of a more traditionl relational database, such as MySQL or Postgres, it is a document database. It has dynamic schemas and stores data using JSON-style documents. This is a why it's so wildly popular amongst Node.js developers who yearn for full-stack Javascript.

The first step to getting Mongo setup in your Sinatra app is to install Mongo. A simple brew install mongodb is all it takes. Then in your Sinatra app's Gemfile just add gem 'mongo' and then run bundle install (or just bundle).

Inside your app.rb or server.rb file include the Mongo module with include Mongo. Now, if you're planning on putting your app up on Heroku then you'll almost certainly end up using MongoHQ. To make your app work both locally and on Heroku you'll want to add the following:

  if ENV['MONGOHQ_URL']
    db = URI.parse(ENV['MONGOHQ_URL'])
    db_name = db.path.gsub(/^\//, '')
    db_connection = Mongo::Connection.new(db.host, db.port).db(db_name)
    db_connection.authenticate(db.user, db.password) unless (db.user.nil? || db.user.nil?)
    db_connection
    set :mongo_db, db_connection
  elsif ENV["RACK_ENV"] == 'test'
    conn = MongoClient.new("localhost", 27017)
    set :mongo_db, conn.db('DATABASE_NAME')
  else
    conn = MongoClient.new("localhost", 27017)
    set :mongo_db, conn.db('DATABASE_NAME')
  end

This bit of code has you covered if you run your app locally in development, locally in your test environment, or up on Heroku in production. Obviously if you don't want it setup for Heroku or for testing then you can remove the relevant bits of code.

With all of that setup you can then setup a collection like so:

my_collection =  mongo_db['DATABSE_NAME']['COLLECTION_NAME']

And now you're ready to start adding documents to your collection by using the following syntax:

my_collection.insert( { text: "some text", time: Time.now } )

It's that easy to get up and running with Mongo in a Sinatra app. I'll definitely be using it more in the future, both in Ruby and Node apps.