[ruby-on-rails] How to define custom configuration variables in rails

I was wondering how to add custom configuration variables to a rails application and how to access them in the controller, for e.g I wanna be able to define an upload_directory in the configuration files say development.rb and be able to access it in one of my controllers.

Secondly I was planning to have S3 support for uploads in my application, if i wanted to add a yaml file with the s3 access, secret key, how do I initialize it in my Rails App and how do I access the values that I have defined in that config file.

This question is related to ruby-on-rails configuration

The answer is


I would suggest good approach how to deal with configuration in your application at all. There are three basic rules:

  • change your configuration not a code;
  • use configurations over conditions;
  • write code that means something.

To have more detailed overview follow this link: Rails configuration in the proper way


Check out this neat gem doing exactly that: https://github.com/mislav/choices

This way your sensitive data won't be exposed in open source projects


I really like the settingslogic gem. Very easy to set up and use.

https://github.com/binarylogic/settingslogic


I created a simple plugin for YAML settings: Yettings

It works in a similar fashion to the code in khelll's answer, but you only need to add this YAML configuration file:

app/config/yetting.yml

The plugin dynamically creates a class that allows you to access the YML settings as class methods in your app like so:

Yetting.your_setting

Also, if you want to use multiple settings files with unique names, you can place them in a subdirectory inside app/config like this:

app/config/yettings/first.yml
app/config/yettings/second.yml

Then you can access the values like this:

FirstYetting.your_setting
SecondYetting.your_setting

It also provides you with default settings that can be overridden per environment. You can also use erb inside the yml file.


This works in rails 3.1:

in config/environment.rb (or in config/environments/.. to target a specific environment) :

YourApp::Application.config.yourKey = 'foo'

This will be accessible in controller or views like this:

YourApp::Application.config.yourKey

(YourApp should be replaced by your application name.)

Note: It's Ruby code, so if you have a lot of config keys, you can do this :

in config/environment.rb :

YourApp::Application.configure do
  config.something = foo
  config.....
  config....
  .
  config....
end

If you use Heroku or otherwise have need to keep your application settings as environment variables, the figaro gem is very helpful.


Something we've starting doing at work is the ActiveSupport Ordered Hash

Which allows you to define your configuration cleanly inside the environment files e.g.

config.service = ActiveSupport::OrderedOptions.new
config.service.api_key = ENV['SERVICE_API_KEY']
config.service.shared_secret = ENV['SERVICE_SHARED_SECRET']

In Rails 3, Application specific custom configuration data can be placed in the application configuration object. The configuration can be assigned in the initialization files or the environment files -- say for a given application MyApp:

MyApp::Application.config.custom_config_variable = :my_config_setting

or

Rails.configuration.custom_config_variable = :my_config_setting

To read the setting, simply call the configuration variable without setting it:

Rails.configuration.custom_config_variable
=> :my_config_setting

UPDATE Rails 4

In Rails 4 there a new way for this => http://guides.rubyonrails.org/configuring.html#custom-configuration

enter image description here


In Rails 4

Assuming you put your custom variables into a yaml file:

# config/acme.yml
development:
  :api_user: 'joe'
  :api_pass: 's4cret'
  :timeout: 20

Create an initializer to load them:

# config/initializers/acme.rb
acme_config = Rails.application.config_for :acme

Rails.application.configure do
  config.acme = ActiveSupport::OrderedOptions.new
  config.acme.api_user = acme_config[:api_user]
  config.acme.api_pass = acme_config[:api_pass]
  config.acme.timeout  = acme_config[:timeout]
end

Now anywhere in your app you can access these values like so:

Rails.configuration.acme.api_user

It is convenient that Rails.application.config_for :acme will load your acme.yml and use the correct environment.


Since Rails 4.2, without additional gems, you can load config/hi.yml simply by using Rails.application.config_for :hi.

For example:

  1. touch config/passwords.yml

        #config/passwords.yml
        development:
          username: 'a'
          password: 'b'
        production:
          username: 'aa'
          password: 'bb'
    
  1. touch config/initializers/constants.rb

    #config/initializers/constants.rb
    AUTHENTICATION = Rails.application.config_for :passwords
    
  1. and now you can use AUTHENTICATION constant everywhere in your application:

    #rails c production
    :001> AUTHENTICATION['username'] => 'aa'
    
  2. then add passwords.yml to .gitignore: echo /config/passwords.yml >> .gitignore, create an example file for your comfort cp /config/passwords.yml /config/passwords.example.yml and then just edit your example file in your production console with actual production values.


I like to use rails-settings for global configuration values that need to be changeable via web interface.


I just wanted to update this for the latest cool stuff in Rails 4.2, you can now do this inside any of your config/**/*.rb files:

config.x.whatever.you.want = 42

...and this will be available in your app as:

Rails.configuration.x.whatever.you.want

See more here: http://guides.rubyonrails.org/configuring.html#custom-configuration


In Rails 3.0.5, the following approach worked for me:

In config/environments/development.rb, write

config.custom_config_key = :config_value

The value custom_config_key can then be referenced from other files using

Rails.application.config.custom_config_key