2012-05-28 8 views
24

Tengo un proyecto sin fines de rieles en el que yo estoy cargando algunos ajustes desde un archivo YAML:Hash con acceso indiferente

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

sólo puedo acceder a este hash como config["host"], etc. config["username"]

I quiero acceso indiferente, así que puedo usar tanto :host como "host".

La razón es que una de las gemas en el proyecto a la que estoy pasando este hash parece acceder a ella usando símbolos y falla actualmente.

¿Cuál es la mejor manera de crear un hash con acceso indiferente en este escenario?

+10

Incluso si usted no está utilizando rieles hay ninguna razón por la que no podría requerir ' 'active_support/core_ext/almohadilla/indifferent_access'', y no es su solución? – Casper

+2

No he instalado la gema active_support y me preguntaba si debería instalarla solo para obtener esta característica. – Josnidhin

+0

Si no lo desea, copie y pegue el código en su propio hash con clase de acceso indiferente. No he mirado la solución de Rails, pero ya la he escrito antes, no puede haber más de 50 LOC. –

Respuesta

15

Vamos el hash config devuelve el valor para la versión stringified de la llave:

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" 

Los default_proc ejecuta cada vez que cuando no se encuentra una llave en el hash. Tenga en cuenta que esto es solo la mitad del acceso indiferente: config["host"] dará como resultado nil si la clave :host está presente. Si eso tiene que trabajar demasiado:

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 
+8

Esto funcionará para el acceso a través de '[]' pero no para cosas como 'borrar' donde tendrá que dar la versión correcta de la clave. Solo para que esté al tanto. – iain

+2

Tenga en cuenta también que no impedirá que alguien agregue dos claves: 'host' y: host con diferentes valores asignados. Si tiene clave 'host' en su Hash y agregue la clave: host el segundo no sobrescribirá ¡el primero! – wrzasa

42

No pierde nada excepto algunos kB de espacio en disco al instalar la joya de Soporte activo. En su código, se necesita sólo la función que desee:

require 'active_support/core_ext/hash/indifferent_access' 

esta manera, usted puede estar seguro de que no está recibiendo nada más que estropear su espacio de nombres.

+1

Sí, pero luego cosas como esta rompen :(- "% {version}"% {version: 5} .with_indifferent_access.to_hash porque estoy adivinando cadenas internas como se usan en lugar de símbolos :( –

+0

Observación interesante. De hecho enseñaste un truco que ni siquiera sabía aquí :-), y veo, de hecho no funciona con esos hashes indiferentes de ActiveSupport. A corto plazo, no puedo decir si esto puede remediarse, pero harías una buena acción para la comunidad de Ruby si desea enviar un ticket para este efecto a los desarrolladores de ActiveSupport. –

Cuestiones relacionadas