Рельсы загружают 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


какие мысли?

742   9  

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 уже должен быть загружен, если вы делаете это в своей среде для использования в инициализаторах и т. д. (как и я).

  1. Rails имеет специальный метод для обозначения клавиш.
  2. Вы можете использовать метод load_file и избавиться от файла.читайте
  3. Не уверен, что вам нужно 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

    Ничего не найдено.