Ответ 1
Попробуйте использовать HashWithIndifferentAccess, например
APP_CONFIG = HashWithIndifferentAccess.new(YAML.load(File.read(File.expand_path('../app.yml', __FILE__))))
Я загружаю файл YAML в Rails 3.0.9 следующим образом:
APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__)))
Он загружает все содержимое, как иерархические хеши, без проблем. Части, которые мне не нравятся, это тот факт, что хеши могут быть доступны только с одиночными или двойными кавычками, но не с символом.
APP_CONFIG['mailer']['username'] # works fine
APP_CONFIG[:mailer][:username] # doesn't
Любые мысли?
Попробуйте использовать HashWithIndifferentAccess, например
APP_CONFIG = HashWithIndifferentAccess.new(YAML.load(File.read(File.expand_path('../app.yml', __FILE__))))
Альтернативным решением является наличие ключей, к которым вы хотите получить доступ, в качестве символа, предшествующего двоеточию. Например:
default: &default
:symbol: "Accessed via a symbol only"
string: "Accessed via a string only"
development:
<<: *default
test:
<<: *default
production:
<<: *default
Затем вы можете получить доступ к ним следующим образом:
APP_CONFIG[:symbol]
APP_CONFIG['string']
Обратите внимание, что я использую YAML::ENGINE.yamler = "syck"
. Не уверен, что это работает с psych
. (Psych определенно не будет поддерживать ключевое слияние, как я показал в примере.)
Об использовании HashWithIndifferentAccess
: с его использованием имеет побочный эффект создания повторяющихся ключей: один для доступа к символам и один для доступа к строкам. Это может быть неосновательно, если вы передаете данные YAML в виде массивов. Помните об этом, если вы пойдете с этим решением.
Если вы работаете в Ruby on Rails, вы можете взглянуть на symbolize_keys(), что делает именно то, что OP попросил о. Если хэш глубокий, вы можете использовать deep_symbolize_keys()
. Используя этот подход, ответ
APP_CONFIG = YAML.load(File.read(File.expand_path('../app.yml', __FILE__))).deep_symbolize_keys
Это то же самое от выбранного ответа, но с лучшим синтаксисом:
YAML.load(File.read(file_path)).with_indifferent_access
Есть еще один потенциальный ответ, который я обнаружил, копаясь.
Вы можете отказаться от HashWithIndifferentAccess.new, добавив это в начало своих файлов YAML:
--- !map:HashWithIndifferentAccess
то просто YAML.load, как обычно. Единственный трюк в том, что рельсы должны быть уже загружены, если вы делаете это в своей среде для использования в инициализаторах и т.д. (Например, я).
Я бы написал так просто:
YAML::load_file('app.yml').symbolize_keys
Вероятно, вы привыкли к хэшу params в Rails, который на самом деле является HashWithIndifferentAccess, а не стандартным объектом ruby Hash. Это позволяет использовать любые строки, такие как "действие" или такие символы, как: действие для доступа к содержимому.
С HashWithIndifferentAccess вы получите те же результаты независимо от того, что используете, но имейте в виду, что это работает только с объектами HashWithIndifferentAccess.
Итак, чтобы сделать эту работу с YAML, вам придется загрузить результат YAML.load в HashWithIndifferentAccess, например:
APP_CONFIG = HashWithIndifferentAccess.new( YAML.load(File.read(File.expand_path('../app.yml', __FILE__))) )
Если вы используете чистый Ruby (т.е. Rails), вы можете вносить изменения в формат JSON. Метод JSON lib parse
может символизировать ключи.
http://ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html#method-i-parse
Вот что я имею в виду:
JSON.parse(JSON.dump(YAML.load_file(File.expand_path('../app.yml', __FILE__))), symbolize_names: true)
Примечание. Это добавляет накладные расходы на преобразование в json и из него.