These days, I use environment variables for credentials and other sensitive data (secrets.yml could do the job but is too boilerplate-y for my taste). Fake environment values are stored in my project dotenv file and production values are deployed to the PaaS server of my choice with a simple heroku config:set / eb setenv / etc.

But what about non-sensitive configuration values such as emails or your company address?

Storing them in environment variables both in your project and in your server can be overkill and not really compliant with 12 factor apps. Those values are best stored in your project source code, in some sort of configuration file.

Rails 4.2 introduced a custom configuration object that can be accessed with Rails.configuration.x, and Rails.application.config_for loads YAML file values depending on the environment. By combining those two features, you can have all your custom configuration in a handy all-in-one YAML file!

Say your project is called MyApp:

  • Create a my_app.yml file in the config directory. It would look something like this:

    # MyApp custom configuration.
    # Do not put sensitive data in this file (use environment variables instead).
    
    default: &default
      emails:
        support: support@my-app.com
        marketing: marketing@my-app.com
      company_address: 221B Baker Street
    
    production:
      <<: *default
    
    development:
      <<: *default
      emails:
        support: support+dev@my-app.com
    
    test:
      <<: *default
    
  • Add this line in your config/application.rb file:

    # ...
    
    module MyApp
      class Application < Rails::Application
        # ...
    
        # Custom configuration
        config.x = Hashie::Mash.new(Rails.application.config_for(:my_app))
      end
    end
    

    I wrapped the loaded configuration hash in a hashie Mash object for convenience, so that I can access configuration variables with dots rather than brackets. It’s like OpenStruct but with nested hash support.

  • You can now access your configuration variables anywhere in your app like so:

    Rails.configuration.x.emails.support
    

I hope that Rails will improve its secret and configuration handling in future releases so that they can be even easier to use out of the box. But for now, this will do!