Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails load YAML to hash and reference by symbol

I am loading a YAML file in Rails 3.0.9 like this:

APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__)))

It loads the all of the contents like hierarchical hashes, no problem. The part I don't like is the fact that the hashes can only be accessed with single or double quotes but not a symbol.

APP_CONFIG['mailer']['username']  # works fine
APP_CONFIG[:mailer][:username]    # doesn't

Any thoughts?

like image 261
Michael K Madison Avatar asked Aug 16 '11 02:08

Michael K Madison


4 Answers

Try using the HashWithIndifferentAccess like

APP_CONFIG = HashWithIndifferentAccess.new(YAML.load(File.read(File.expand_path('../app.yml', __FILE__))))
like image 126
Rob Di Marco Avatar answered Nov 08 '22 10:11

Rob Di Marco


An alternative solution is to have the keys which you wish to access as a symbol prepended with a colon. For example:

default: &default
  :symbol: "Accessed via a symbol only"
  string: "Accessed via a string only"

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default

Later you can then access these like so:

APP_CONFIG[:symbol]
APP_CONFIG['string']

Note that I am using YAML::ENGINE.yamler = "syck". Not sure if this works with psych. (Psych definitely won't support key merging as I showed in the example though.)

About using HashWithIndifferentAccess: using it has the side effect of creating duplicate keys: one for symbol access and one for string access. This might be nefarious if you pass around YAML data as arrays. Be aware of this if you go with that solution.

like image 24
istvanp Avatar answered Nov 08 '22 10:11

istvanp


If you are working in Ruby on Rails, You might want to take a look at symbolize_keys(), which does exactly what the OP asked for. If the hash is deep,you can use deep_symbolize_keys(). Using this approach, the answer is

APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__))).deep_symbolize_keys
like image 29
zentralmaschine Avatar answered Nov 08 '22 11:11

zentralmaschine


Psych (a.k.a. YAML) provides the keyword argument :symbolize_names to load keys as symbols. See method reference

file_path = File.expand_path('../app.yml', __FILE__)
yaml_contents = File.read(file_path)
    
APP_CONFIG = YAML.safe_load(yaml_contents, symbolize_names: true)
like image 18
bbenno Avatar answered Nov 08 '22 12:11

bbenno