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. Principal ventaja es que, se lee como archivo de texto. Esto funciona muy bien si su archivo de configuración es plana (sin jerarquía) y no tiene repeticiones.
Si su archivo de configuración tiene repeticiones, entonces tiene sentido para separar los elementos y volver a usarlos. Lo que quiero decir es esto - vamos a decir que su archivo de configuración es la siguiente:

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

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

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


$ cat readyml.rb

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

aquí hay una mano una camisa de Rubí
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' o puede tratar de la misma en el IRB o la consola de python.

Tenga en cuenta que en el código anterior, todo es distinto de ubicación de salida es la misma, en parte, el desarrollo y la producción. Aquí es donde identificador de nodo yml viene al rescate. Idea es simple tener un conjunto de valores predeterminados y reemplazar ellos en lugar diferente.
Se podía separar de la siguiente manera:

  por defecto: y por defecto
   input_location: common_input
   output_location: dev_location
   mail:
     sender_name: emisor
     smtp_server: suServidor
     login: your_login
     contraseña: top_secret
 el desarrollo:
   <<: * Por defecto
 producción:
   <<: * Por defecto
   output_location: prod_location 


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

Grandes, que funciona (tm)!.
Podría decirse que negocian un poco de claridad a un poco de magia. Aquí hay una pequeña explicación: y, * y <<: y que se etiqueta de anclaje puede ser entendido como identificador de nodo, * es nodo de referencia y <<: significa combinar hash.

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

  por defecto: y por defecto
   input_location: common_input
   output_location: dev_location
   mail:
     sender_name: emisor
     smtp_server: suServidor
     login: your_login
     contraseña: top_secret
 el desarrollo:
   <<: * Por defecto
   mail:
     sender_name: sender_dev
 producción:
   <<: * Por defecto
   output_location: prod_location
   mail:
     sender_name: sender_prod 

Permite comprobar

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

Vaya, algo salió mal, el problema como se mencionó anteriormente es que la combinación hash no es recurrente y si bien la fusión de lo reemplazó por correo electrónico de incumplimiento por parte de la producción que tiene una sola llave. Solución / solución es desenrollar un nivel más:

  common_settings: y common_settings
 input_location: common_input
 output_location: dev_location
 mail_defaults: y mail_defaults
  sender_name: emisor
   smtp_server: suServidor
   login: your_login
   contraseña: top_secret

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

Permite comprobar de nuevo

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

¿Sabía usted que usted tiene un nivel más de anidación, así que definitivamente se puede desenrollar un nivel más, pero entonces se convierte en un desastre. Por lo tanto, si usted no está tratando de escribir la solución a las torres de Hanoi, en un archivo de conf, es mejor restucture archivo conf que cavar en YAML o algo más. Pero eso es la llamada de todos modos.