Example code for storing environment-specific configuration variables in rails

Here’s some example code I’ve used for storing configuration variables using Ruby on Rails. This code allows for defaults as well, so you only have to specify variables per environment if they override the default value.

This first file should be put in /lib/app_config.rb.

# This singleton class stores configuration options.
# It makes use of Ruby's method_missing method
# Any option added to the application's config file
# is automatically available as a method of the same name.
#
class AppConfig
  include Singleton

  # This file is used to set the configuration options for the application.
  CONFIG_FILE = "#{RAILS_ROOT}/config/application.yml"

  def initialize
    @parser = YamlAppConfigParser.new(CONFIG_FILE)
  end

  def method_missing(methId)
    instance_sym = ("@" + methId.id2name).to_sym
    instance_variable_set(instance_sym, @parser.send(methId)) unless     instance_variable_get(instance_sym)
    instance_variable_get(instance_sym)
  end
end

The above code uses method_missing to create methods on the fly that correspond to different configuration variables. Add the config variable, and it automatically becomes available as a method on the AppConfig singleton class.

You need this class to load and parse the yaml file that the data is stored in. It should be in /lib/yaml_app_config_parser.rb.


# This class parses /config/application.yml
# It supports both default and environment options.
# Environment options override the default options.
class YamlAppConfigParser

  def initialize(yaml_file)
    @yaml = YAML.load_file(yaml_file)
  end

  def method_missing(methId)
    if @yaml[RAILS_ENV] && @yaml[RAILS_ENV][methId.id2name]
      @yaml[RAILS_ENV][methId.id2name]
    else
      @yaml['default'][methId.id2name]
    end
  end
end

The above 2 files you just put in your project and forget about. Then, you just add config values to the /config/application.yml file, and they become available config variables that vary by environment.

Here’s what a basic/config/application.yml might look like.


default:
  facebook_app_id: adsf78yadfkjasdf807y
  facebook_secret: adsf78yadfkjasdf807y
  path_to_file_foo: /mnt/files/foo.bar

development:
  path_to_file_foo: /User/MyUser/tmp/files/foo.bar

production:
  facebook_app_id: my_prod_fb_app_id
  facebook_secret: my_prod_secret

Notice that the production environment has its own facebook_app_id and facebook_secret values, while the development environment just uses the default values. That’s how this approach works – you override only what you need.

Now to access these values from your code is simple, you just call:

  @facebook_app_id = AppConfig.instance.facebook_app_id
  @facebook_secret = AppConfig.instance.facebook_secret
  @path_to_file_foo = AppConfig.instance.path_to_file_foo

Then the variables you’ve set as above contain the configuration values specific to their environment.

This entry was posted in code, programming, rails, ruby on rails and tagged , , . Bookmark the permalink.
  • Friendly Rubyist

    Thanks for the handy code. One note – the yaml_app_config_parser doesn’t handle bools correctly. It can be corrected by changing the first if-check to the following:

        if @yaml[Rails.env] && @yaml[Rails.env].has_key?(methId.id2name)

    Current score: 0