ruby-on-rails - multi - rails translation interpolation
Los raíles cargan YAML en hash y referencia por símbolo (9)
Estoy cargando un archivo YAML en Rails 3.0.9 de esta manera:
APP_CONFIG = YAML.load(File.read(File.expand_path(''../app.yml'', __FILE__)))
Carga todos los contenidos como hashes jerárquicos, no hay problema. La parte que no me gusta es el hecho de que los hashes solo se pueden acceder con comillas simples o dobles, pero no con un símbolo.
APP_CONFIG[''mailer''][''username''] # works fine
APP_CONFIG[:mailer][:username] # doesn''t
¿Alguna idea?
- Rails tiene un método especial para simbolizar claves.
- Puede usar el método load_file y deshacerse de File.read
- No estoy seguro si necesita expand_path también, el directorio predeterminado es rails root.
Lo escribiría así de simple:
YAML::load_file(''app.yml'').symbolize_keys
Esto es lo mismo de la respuesta seleccionada, pero con una mejor sintaxis:
YAML.load(File.read(file_path)).with_indifferent_access
Hay otra respuesta potencial que descubrí mientras cavaba.
Puede renunciar a HashWithIndifferentAccess.new agregando esto en la parte superior de sus archivos YAML:
--- !map:HashWithIndifferentAccess
luego simplemente YAML.carga como normal. El único truco es que los rieles ya deben estar cargados si estás haciendo esto en tu entorno para utilizarlos en inicializadores, etc. (como yo).
Intente usar el HashWithIndifferentAccess como
APP_CONFIG = HashWithIndifferentAccess.new(YAML.load(File.read(File.expand_path(''../app.yml'', __FILE__))))
Normalmente no uso HashWithIndifferentAccess
solo para evitar confusiones y evitar incoherencias en la forma en que se accede, por lo que lo que haría en lugar de eso es .deep_symbolize_keys
un .deep_symbolize_keys
para obtener todo en forma de clave de símbolo.
Probablemente esté acostumbrado al hash de params en Rails, que en realidad es un HashWithIndifferentAccess en lugar de un objeto estándar de ruby Hash. Esto le permite usar cadenas como ''acción'' o símbolos como: acción para acceder a los contenidos.
Con un HashWithIndifferentAccess, obtendrá los mismos resultados independientemente de lo que use, pero tenga en cuenta que esto solo funciona en los objetos HashWithIndifferentAccess.
Para que esto funcione con YAML, tendrá que cargar el resultado de YAML.load en un HashWithIndifferentAccess, así:
APP_CONFIG = HashWithIndifferentAccess.new( YAML.load(File.read(File.expand_path(''../app.yml'', __FILE__))) )
Si está trabajando en Ruby on Rails, tal vez quiera echar un vistazo a symbolize_keys() , que hace exactamente lo que el OP solicitó. Si el hash es profundo, puedes usar deep_symbolize_keys()
. Usando este enfoque, la respuesta es
APP_CONFIG = YAML.load(File.read(File.expand_path(''../app.yml'', __FILE__))).deep_symbolize_keys
Si está usando Ruby puro (es decir, sin rieles), puede cambiar de forma intermedia al formato JSON. El método de parse
JSON lib puede simbolizar claves.
http://ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html#method-i-parse
Esto es lo que quiero decir:
JSON.parse(JSON.dump(YAML.load_file(File.expand_path(''../app.yml'', __FILE__))), symbolize_names: true)
Nota : Esto agrega una sobrecarga de conversión hacia y desde json.
Una solución alternativa es tener las teclas a las que desea acceder como un símbolo precedido de dos puntos. Por ejemplo:
default: &default
:symbol: "Accessed via a symbol only"
string: "Accessed via a string only"
development:
<<: *default
test:
<<: *default
production:
<<: *default
Más tarde, puede acceder a estos de la siguiente manera:
APP_CONFIG[:symbol]
APP_CONFIG[''string'']
Tenga en cuenta que estoy usando YAML::ENGINE.yamler = "syck"
. No estoy seguro si esto funciona con psych
. (Sin embargo, Psych definitivamente no admitirá la fusión de claves como lo mostré en el ejemplo).
Acerca del uso de HashWithIndifferentAccess
: su uso tiene el efecto secundario de crear claves duplicadas: una para el acceso a símbolos y otra para el acceso a cadenas. Esto podría ser nefasto si pasa datos de YAML como matrices. Sé consciente de esto si vas con esa solución.