La fusión de los hashes de los archivos conf YAML

31 de julio 2009 por prashant · Comentarios
Filed under: tecnología

YAML es muy útil para escribir archivos de configuración. Su principal ventaja es que, se lee como archivo de texto. Esto funciona muy bien si su fichero de configuración es plana (sin jerarquía) y no tiene repeticiones.
Si la configuración de su archivo es de repeticiones, entonces tiene sentido separar los elementos y reutilizarlos. Lo que quiero decir es esto - digamos que su archivo de configuración es similar a esto:

  el desarrollo:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: your_server
     entrada: your_login
     contraseña: top_secret
 producción:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: your_server
     entrada: your_login
     contraseña: top_secret 

Suponiendo que el código de seguridad en / tmp / test.yml aquí es cómo se puede leer en Python y Ruby
$cat readyml.py

 #! / Usr / bin / env python
 de pprint pprint importación pp
 # Debian en la necesidad de instalar python-YAML
 de la carga de importación YAML, load_all, volcado
 hash = carga (abierto ('/ tmp / test.yml'))
 pp (hash desarrollo [']) 


$ cat readyml.rb

  #! / Usr / bin / env ruby
 require 'pp'
 hash = YAML:: load (File.open ('/ tmp / test.yml »). leer)
 desarrollo [pp hash '] 

aquí hay una mano una línea de la versión rubí
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' o puede probar de la misma en irb o consola de python.

Tenga en cuenta que en el fragmento de código anterior, todo es distinto de ubicación de salida es la misma en el desarrollo y la producción una parte. Aquí es donde identificador de nodo yml viene a rescatar. La idea es sencilla con un conjunto de valores por defecto y por encima de ellas en lugar diferente.
Usted podría separarla de la siguiente manera:

  por defecto: y por defecto
   input_location: common_input
   output_location: dev_location
   mail:
     sender_name: emisor
     smtp_server: your_server
     entrada: your_login
     contraseña: top_secret
 el desarrollo:
   <<: Valores predeterminados *
 producción:
   <<: Valores predeterminados *
   output_location: prod_location 


$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$

Grande, funciona (tm)!.
Podría decirse que negocian cierta claridad por un poco de magia. He aquí una pequeña explicación: & *, y <<: & que se etiqueta de anclaje puede ser entendido como identificador de nodo, * es el nodo de referencia y <<: significa hash fusión.

Para más detalles vea bien Ficha YAML o wikipedia
Hasta aquí todo bien, pero hay un problema aquí, estos se une hash no son recursivos. Lo que significa es esto: digamos que usted desea tener el nombre del remitente del correo diferentes en dos ambientes, puede tener la tentación de hacer lo siguiente:

  por defecto: y por defecto
   input_location: common_input
   output_location: dev_location
   mail:
     sender_name: emisor
     smtp_server: your_server
     entrada: your_login
     contraseña: top_secret
 el desarrollo:
   <<: Valores predeterminados *
   mail:
     sender_name: sender_dev
 producción:
   <<: Valores predeterminados *
   output_location: prod_location
   mail:
     sender_name: sender_prod 

Le permite comprobar la

$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
nil
$

Uy, algo salió mal, el problema como se ha mencionado es que la combinación hash no es recursiva, y al mismo tiempo que la fusión sustituirá correo electrónico de incumplimiento por parte de la producción que sólo tiene una clave. Solución / evitar es desenrollar un nivel más:

  common_settings: & common_settings
 input_location: common_input
 output_location: dev_location
 mail_defaults: & mail_defaults
  sender_name: emisor
   smtp_server: your_server
   entrada: your_login
   contraseña: top_secret

 por defecto: y por defecto
   <<: * Common_settings
   mail:
     <<: * Mail_defaults
 el desarrollo:
   <<: Valores predeterminados *
 producción:
   <<: Valores predeterminados *
   mail:
     <<: * Mail_defaults
     sender_name: sender_prod

Vamos a comprobar de nuevo

$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$

¿Ha dicho usted tiene un nivel más de anidamiento, así que definitivamente puede desenrollar un nivel más, pero entonces se convierte en un lío. Así pues, si usted no está tratando de escribir una solución a las torres de hanoi en un archivo de conf, que es mejor restucture archivo conf que excavar en YAML o algo más. Pero eso es su deber de todos modos.