Simplifying ActiveRecord Connection Strings
Over the years I've gone to great lengths to avoid committing production
passwords into version control. With Rails this has inevitably meant a
number of different ways to ensure the
database.yml was where it needed to
be on the production servers, with the right credentials. Custom Capistrano
recipes to create a new config when setting up a server, moving it into
place after a deploy, it worked well enough but it's always felt a little
There's got to be a better way
There are a whole range of configuration settings that are environment dependent. Which database to connect to, what queues Resque workers should listen to, the Rack/Application environment mode. What we need is a standard way on each server to set these environment variables. Oh hang on, environment variables!
It's easy enough to either export an environment variable in a shell, or
pass it in with the command like
RACK_ENV=production rackup config.ru
but a more complicated configuration like ActiveRecord requires doesn't
quite work like that. It's expecting a Hash that defines the database
adapter to use, username, password, the database, a host, and possibly a
bunch of other options. We could probably serialise that back and forth
between a Hash and something like JSON but it feels like a bit of a hack.
What would be better is if we could come up with a simple and uniform string format that could define how to locate any resource, including a database. I propose we call such a string a Uniform Resource Locator, or URL for short 😉
Using URLs to connect to databases
This isn't a new technique, other ORMs like Sequel have been doing this for years. It's just that ActiveRecord hasn't supported it, until now. I've created a gem that adds support for URL based connections to ActiveRecord, it's called activerecordurlconnections.
Add it to your
And now you can connect to your database by adding the following to an
Now you can either export the
DATABASE_URL environment variable in your
app environment or set it when you start your app like so:
No more juggling
database.yml on production servers, no risk of checking
sensitive credentials into version control.
Convention Over Configuration
Something still doesn't feel quite right about this approach though. Creating
an initializer just to have that one line seems a bit needless, especially
when it will be exactly the same in almost every app. So in much the same
way Rails assumes a default connection to use if you don't provide one, so
it will look to see if you've set
DATABASE_URL and use it when available.
Stick with the conventions, and you'll not need to do anything beyond adding
the gem and setting
But wait, there's more!
There's some further good news too. Firstly, for anyone using Heroku for
hosting Rack apps that use ActiveRecord this means connection to your
database will "just work" (it's not needed for Rails as Heroku create a
database.yml file so the existing Rails behaviour will work). Secondly
this change has made it into ActiveRecord for the 3.2 release so you'll
only need this gem to backport the behaviour to previous releases.