DRY out your database.yml

27 Jun 2006

While paging through my RSS aggregator this afternoon, I came across James Duncan Davidson’s article Conditional Rails Database Configuration. “Damn”, thought I, “ERb in the database.yml is a neat trick, but it’s so ugly!”

That reminded me of a little trick I’ve been using for as long as I can remember. I can’t take credit for this technique as I learned it from someone else… I just don’t remember who. Anyway, it goes a little something like this:

login: &login
  adapter: mysql
  username: username
  password: password
  host: mysql.example.com

development:
  <<: *login
  database: app_dev

test:
  <<: *login
  database: app_test

production:
  <<: *login
  database: app_prod

That’s a pretty standard Rails database.yml, all DRYed out. Like I said, I’ve been doing this forever but I rarely see it in other apps.

To extend on James’ post, here’s what his example would look like if you follow this technique:

common: &common
  adapter: mysql

dev: &dev
  <<: *common
  username: root
<% if File.exist? "/opt/local/var/run/mysql5/mysqld.sock" %>
  socket: /opt/local/var/run/mysql5/mysqld.sock
<% elsif File.exist? "/tmp/mysql.sock" %>
  socket: /tmp/mysql.sock
<% end %>

development:
  <<: *dev
  database: birdy

test:
  <<: *dev
  database: birdy_test

production:
  <<: *common
  host: 10.0.1.24
<% if `uname -n`.strip == "staging" %>
  database: birdy_stage
  username: birdy_stage
  password: somethingsecret
<% else %>
  database: birdy
  username: birdy
  password: somethingelsethatissecret
<% end %>

Okay okay, it’s ugly for sure. But it’s functional and repetition has been removed where possible, making it less ugly than before. Of course you could get even trickier and tweak with the conditionals in the Production environment, but then you start getting into spaghetti ERb in your database.yml, which has got to be some sort of sin.

So there you go. I’d dearly love to see this method gain more popularity as it’s so much cleaner. I can’t be the only one whose development environment is close enough to his production environment to let this work!

Update: Matt says that Typo uses this scheme for their database.yml, which is likely where I first saw it. Jonathan mentions that this is also included in Rails Recipes, which I have to admit I’ve owned since the day it came out as a betabook but never actually looked at. Thanks, guys!

« go back