Хэш с безразличным доступом

У меня есть проект non-Rails, в котором я загружаю некоторые параметры из файла YAML:

config = YAML::load(File.open("#{LOG_ROOT}/config/database.yml"))

Я могу получить доступ только к этому хешу, например config["host"], config["username"] и т.д.

Я хочу безразличный доступ, чтобы использовать как :host, так и "host".

Причина в том, что один из камней в проекте, к которому я передаю этот хеш, похоже, обращается к нему с использованием символов, и в настоящее время он терпит неудачу.

Какой лучший способ создать хэш с равнодушным доступом в этом сценарии?

Ответ 1

Пусть хэш-код конфигурации возвращает значение для строковой версии ключа:

config = {"host"=>"value1", "Username"=>"Tom"}
config.default_proc = proc{|h, k| h.key?(k.to_s) ? h[k.to_s] : nil}
p config[:host] #=> "value1"

default_proc запускается каждый раз, когда ключ не найден в хэше. Обратите внимание, что это только половина безразличного доступа: config["host"] приведет к нулю, если присутствует ключ :host. Если это тоже нужно:

config.default_proc = proc do |h, k|
   case k
     when String then sym = k.to_sym; h[sym] if h.key?(sym)
     when Symbol then str = k.to_s; h[str] if h.key?(str)
   end
end

Ответ 2

Вы ничего не теряете, кроме нескольких килобайт дискового пространства, устанавливая драгоценный камень Active Support. В вашем коде вам требуется только функция, которую вы хотите:

require 'active_support/core_ext/hash/indifferent_access'

Таким образом, вы можете быть уверены, что не получаете ничего другого, чтобы испортить пространство имен.