Heroku-friendly Application Configuration

March 8th, 2011

Heroku is wonderful.

What I love about Heroku is that they stick to their guns. They’re not gonna install MySQL for you. That’s just not how it works. They have a fantastic platform and it runs on PostgreSQL, so… get used to it. Now for some people this hard-line approach might be frustrating but for me, I rarely find myself disagreeing with Heroku’s conventions.

So, onward to the Heroku convention of the hour: application configuration.

When Rails 3 was released, it lost a feature I used quite a bit. You could create a file in config/preinitializer.rb that would be load before the Rails app boots. This is where I littered the app with all sorts of server/environment-specific configuration:

CONSUMER_KEY = "YOUR_CONSUMER_KEY"
CONSUMER_SECRET = "YOUR_CONSUMER_SECRET"
REQUEST_TOKEN = "YOUR_REQUEST_TOKEN"
REQUEST_SECRET = "YOUR_REQUEST_SECRET"
RUBYGEMS_API_KEY = "YOUR_RUBYGEMS_API_KEY"

Once again, Heroku had a better idea. They throw your configuration into ENV, and with the heroku gem, you can configure your production server one ENV variable at a time:

$ heroku config:add CONSUMER_KEY=YOUR_CONSUMER_KEY

But how do you configure your local development environment?

I’ve started including a Git-ignored config/application.yml file that looks something like:

CONSUMER_KEY: YOUR_CONSUMER_KEY
CONSUMER_SECRET: YOUR_CONSUMER_SECRET
REQUEST_TOKEN: YOUR_REQUEST_TOKEN
REQUEST_SECRET: YOUR_REQUEST_SECRET
RUBYGEMS_API_KEY: YOUR_RUBYGEMS_API_KEY

And in my config/application.rb (or config.ru), I include:

require "yaml"

env_path = File.expand_path("../application.yml", __FILE__)
if File.exist?(env_path)
  env = YAML.load_file(env_path)
  env.each{|k,v| ENV[k] = v }
end

This simply loads up your YAML configuration and merges it into ENV.

Note: ENV isn’t a typical hash in your Rails application, so ENV.merge!(env) won’t do the trick.

Heroku’s servers are pleased as punch to honor the configuration added through the heroku gem. Elsewhere, you’re free to include your own configuration. Win win!

blog comments powered by Disqus