Подтвердить что ты не робот

Rails загружает 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

Любые мысли?

4b9b3361

Ответ 1

Попробуйте использовать HashWithIndifferentAccess, например

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

Ответ 2

Альтернативным решением является наличие ключей, к которым вы хотите получить доступ, в качестве символа, предшествующего двоеточию. Например:

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 в виде массивов. Помните об этом, если вы пойдете с этим решением.

Ответ 3

Если вы работаете в Ruby on Rails, вы можете взглянуть на symbolize_keys(), что делает именно то, что OP попросил о. Если хэш глубокий, вы можете использовать deep_symbolize_keys(). Используя этот подход, ответ

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

Ответ 4

Это то же самое от выбранного ответа, но с лучшим синтаксисом:

YAML.load(File.read(file_path)).with_indifferent_access 

Ответ 5

Есть еще один потенциальный ответ, который я обнаружил, копаясь.

Вы можете отказаться от HashWithIndifferentAccess.new, добавив это в начало своих файлов YAML:

--- !map:HashWithIndifferentAccess

то просто YAML.load, как обычно. Единственный трюк в том, что рельсы должны быть уже загружены, если вы делаете это в своей среде для использования в инициализаторах и т.д. (Например, я).

Ответ 6

  • Rails имеет специальный метод для обозначения ключей.
  • Вы можете использовать метод load_file и избавиться от File.read
  • Не уверен, что вам нужен expand_path, каталог по умолчанию - root.

Я бы написал так просто:

YAML::load_file('app.yml').symbolize_keys

Ответ 7

Вероятно, вы привыкли к хэшу 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__)))   )

Ответ 8

Если вы используете чистый 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 и из него.