Flexible Application Configuration in Rails

Most of my rails application have required some form of application specific configuration. When the configuration varies depending on where I deploy it I prefer to externalize the configuration in a YAML file similar to the way database configuration is handled.

I remember reading a blog somewhere that suggested the use of OpenStruct and have since started using the following code placed at the bottom of my config/environment.rb file.

require 'ostruct'
require 'yaml'

ConfigFile = "#{RAILS_ROOT}/config/config.yml"
if File.exist?(ConfigFile)
 ::ApplicationConfig = OpenStruct.new(YAML.load_file(ConfigFile))
end

Consider the scenario where config/config.yml contains;

proxy_config:
  host: proxy.cs.latrobe.edu.au
  port: 8080

I could then access the the configuration data using

>> ApplicationConfig.proxy_config['host'] 
=> "proxy.cs.latrobe.edu.au"
>> ApplicationConfig.proxy_config['port']
=> 8080

To make your code more robust in the scenario where either the proxy configuration is missing or the whole configuration file is missing I generally add in extra guards. Below is an example of the code I use to instantiate a Net:HTTP object. If the configuration file is present and it contains a proxy_config section then the code will attempt to instantiate a Net::HTTP::Proxy object. Otherwise the code will instantiate a plain old Net::HTTP that will not attempt to go via a proxy server.

def http
  if Module.constants.include?("ApplicationConfig") && 
      ApplicationConfig.respond_to?(:proxy_config)
    host = ApplicationConfig.proxy_config['host']
    port = ApplicationConfig.proxy_config['port']
    Net::HTTP::Proxy(host, port)
  else
    Net::HTTP
  end
end