YAML configuration file: Why 'example' instead of :example?

ruby-on-rails, yaml

Solution

By default, a YAML key is rendered as String.

development:
  username: development_name
  password: secret

is accessible by

APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env]
APP_CONFIG['development']['username']
# => "development_name"

I you want a specific key to be a symbol, you should prefix it with : in the YAML file.

development:
  :username: development_name
  :password: secret

APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env]
APP_CONFIG['development'][:username]
# => "development_name"
APP_CONFIG['development']['username']
# => nil

Normally, this is not done because this is a specific Ruby behavior. Other languages might not be happy about the leading :.

If you specifically wants to access keys as symbol, you can either use `symbolize_keys!`

APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env].simbolize_keys!

but most of the time, the effort is not worth. Internally, the 90% of libraries converts Symbols to Strings during a comparison, especially when you deal with hashes with indifferent access. So, at the end of the story, you might want to keep strings in this case.

Last option would be to create a HashWithIndifferentAccess

APP_CONFIG = HashWithIndifferentAccess.new(YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env])

This will allow you to access

APP_CONFIG[:development][:username]
APP_CONFIG['development'][:username]
APP_CONFIG['development']['username']

indifferently. It works by storing the hash keys to string internally and converting the request to `[]` to string, so that it always works. This is the class used by several Rails components, including the famous `params[]` hash in the controllers.

Problem

I set up an environment YAML file for environment specific variables like username and password. To use these variables in my app, I need to use `APP_CONFIG['username']` instead of `APP_CONFIG[:username]`. Why is this? How would I enable the latter instead? Not a major issue, but it bothers me to not know the cause of the difference. config/initializers/load_app_config.rb ``` APP_CONFIG = YAML.load_file("#{Rails.root}/config/app_config.yml")[Rails.env] ``` config/app_config.yml ``` development: username: development_name password: secret production: username: production_name password: super_secret ```

Original source