Configuring Rails Applications
This week I was configuring an application to run different instances depending on the subdomain requested. This is really quite easy: here’s the basic theory DHH used in Basecamp: http://gist.github.com/45076.
Easy enough. But, now, I want to use this only in some environments. In development I want http://localhost:3000 to just be the development instance (
@current_account = Account.first).
I’d love to solve this by adding something like the following to config/environments/development.rb
config.get_instance_from_subdomain = false
Googling, I found a lot of advice about creating custom configuration systems and several plugins that would do it for me. But, IMHO, all of these involved writing too much software. We’ve already got
Rails::Configuration, why reinvent the wheel? In my case, at least, there was no need.
Extending the Wheel
Since it’s quite easy in Ruby to extend classes, I added this block to
Rails::Initializer.run do |config| # extend Rails::Configuration config.class.class_eval do def get_instance_from_subdomain @get_instance_from_subdomain ||= true end def get_instance_from_subdomain=(value) @get_instance_from_subdomain = value end end # ... end
But it wouldn’t be a lot of fun to have to define accessors for every property you need to configure if you have several of them. It would be nicer to add configuration options on the fly – as easily as adding values to a hash. Turns out, the Rails team didn’t want to waste keystrokes writing accessors either. Groups of configuration options (like
config.action_mailer) are actually instances of
Rails::OrderedOptions – an object that lets you add properties at run-time. You can create your own groups of flexible configuration options like this:
Rails::Initializer.run do |config| # extend Rails::Configuration config.class.class_eval do def application_mailer @application_mailer ||= Rails::OrderedOptions.new end end # ... end
Now you can define namespaced configuration just by assigning values to properties of
config.application_mailer.property1 = false config.application_mailer.property2 = :awesome