Рельсы загружают YAML в хэш и ссылку по символу
я загружаю файл 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
какие мысли?
9 ответов:
попробуйте использовать 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 (), который делает именно то, что ОП просил. Если хэш глубокий, вы можете использовать
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.новое, вместо этого добавив это в верхнюю часть ваших файлов YAML:
--- !map:HashWithIndifferentAccessпотом просто в YAML.нагрузка как обычно. Единственный трюк заключается в том, что rails уже должен быть загружен, если вы делаете это в своей среде для использования в инициализаторах и т. д. (как и я).
- Rails имеет специальный метод для обозначения клавиш.
- Вы можете использовать метод load_file и избавиться от файла.читайте
- Не уверен, что вам нужно expand_path также, каталог по умолчанию rails root.
Я бы написал просто:
YAML::load_file('app.yml').symbolize_keys
вы, вероятно, привыкли к хэшу params в Rails, который на самом деле является HashWithIndifferentAccess, а не стандартным объектом Ruby Hash. Это позволяет использовать либо строки, такие как "действие" или символы, такие как :действие для доступа к содержимому.
С HashWithIndifferentAccess, вы получите те же результаты независимо от того, что вы используете, но имейте в виду, что это работает только на hashwithindifferentaccess объектов.
поэтому, чтобы сделать эту работу с YAML, вам придется загрузить результат ЯМЛ.загрузите в HashWithIndifferentAccess, например:
APP_CONFIG = HashWithIndifferentAccess.new( YAML.load(File.read(File.expand_path('../app.yml', __FILE__))) )
Если вы используете чистый Ruby (т. е. без рельсов), вы можете промежуточно перейти на формат JSON. В Библиотека json-ы
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 и из него.
Я обычно не использую
HashWithIndifferentAccessпросто чтобы избежать путаницы и предотвратить несоответствия в том, как он доступен, так что я бы сделал вместо этого Галс на.deep_symbolize_keysчтобы получить все это в виде символа ключа.
Comments