Hash Īmbinarea īn fişierele conf yaml

31 iulie 2009 de Prashant · Comentarii
Filed under: tehnologie

YAML este destul de util pentru scrierea fişierelor de configurare. Avantajul principal este că, se citeşte ca fişier text. Acest lucru functioneaza foarte bine, dacă fişierul dumneavoastră de configurare este plat (nu ierarhie) şi nu are repetiţii.
Dacă fişierul dvs. are configuraţii de repetari, atunci face sens pentru a separa aceste elemente şi reutilizarea lor. Ce vreau să spun este aceasta - să spunem că fişierul de configurare arata ca aceasta:

  de dezvoltare:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: serverului_dvs
     autentificare: your_login
     Parola: top_secret
 de producţie:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: serverului_dvs
     autentificare: your_login
     Parola: top_secret 

Presupunānd că codul de mai sus, īn / tmp / test.yml aici este modul īn care puteţi citi īn Python şi Ruby
$cat readyml.py

 # / Usr! / Bin / env python
 din import pprint pprint ca PP
 # Īn debian trebuie să instalaţi python-yaml
 de la yaml de import de sarcină, load_all, benă
 hash = sarcina (open ('/ tmp / test.yml "))
 PP (hash ["dezvoltare"]) 


$ cat readyml.rb

  # / Usr! / Bin / env ruby
 nevoie de "PP"
 hash = YAML :: sarcina (File.open ('/ tmp / test.yml "). citeşte)
 PP hash ["dezvoltare"] 

aici este la īndemānă o linie pentru versiunea Ruby
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' sau puteţi īncerca acelaşi lucru īn IRB sau consola Python.

Reţineţi că, īn fragmentul de cod de mai sus, totul este altfel decāt īn ​​locaţie de ieşire este aceeaşi īn dezvoltarea şi partea de producţie. Acest lucru este īn cazul īn care identificatorul de nod yml vine pentru a salva. Ideea este simpla avea un set de valori implicite şi suprascrie le īn alt loc.
Ai putea trage afară, după cum urmează:

  valori prestabilite: şi implicite
   input_location: common_input
   output_location: dev_location
   mail:
     SENDER_NAME: expeditor
     smtp_server: serverului_dvs
     autentificare: your_login
     Parola: top_secret
 de dezvoltare:
   : * << Implicite
 de producţie:
   : * << Implicite
   output_location: prod_location 


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

Mare, funcţionează (tm)!.
Se poate spune că am unele tranzacţionate claritate pentru un pic de magie. Aici este o explicaţie mic: &, * si <<: si care este tag-ul ancora poate fi īnţeleasă ca identificator nod, * este nod de referinţă şi <<: standuri pentru īmbinare de distribuire.

Pentru mai multe detalii a se vedea fie Specificatii yaml sau wikipedia
Pānă īn prezent, atāt de bine, dar există o captură aici, aceste īmbinări de hash nu sunt recursiv. Ce īnseamnă aceasta este: să presupunem că doriţi să aveţi nume de expeditor diferit de mail īn două medii, poate fi tentat să facă următoarele:

  valori prestabilite: şi implicite
   input_location: common_input
   output_location: dev_location
   mail:
     SENDER_NAME: expeditor
     smtp_server: serverului_dvs
     autentificare: your_login
     Parola: top_secret
 de dezvoltare:
   : * << Implicite
   mail:
     SENDER_NAME: sender_dev
 de producţie:
   : * << Implicite
   output_location: prod_location
   mail:
     SENDER_NAME: sender_prod 

Vă permite să verificaţi

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

Hopa, ceva a mers gresit, problema cum sa menţionat mai sus, este că īmbinarea hash nu este recursivă şi īn timp ce fuzionează se īnlocuieşte mail implicit prin e-mail de producţie care are doar o cheie. Soluţie / īn jurul valorii de munca este de a derula un nivel mai mult:

  common_settings: & common_settings
 input_location: common_input
 output_location: dev_location
 mail_defaults: & mail_defaults
  SENDER_NAME: expeditor
   smtp_server: serverului_dvs
   autentificare: your_login
   Parola: top_secret

 valori prestabilite: şi implicite
   : * << Common_settings
   mail:
     : * << Mail_defaults
 de dezvoltare:
   : * << Implicite
 de producţie:
   : * << Implicite
   mail:
     : * << Mail_defaults
     SENDER_NAME: sender_prod

Vă permite să verificaţi din nou

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

Ai spune că au un nivel una mai mult de cuiburi, de bine vă puteţi derula cu siguranta un nivel mai mult, dar apoi devine un dezastru. Deci, dacă nu se īncearcă să scrie soluţie pentru turnuri din Hanoi īntr-un fişier conf, este mai bine să restucture fişier conf mult de săpat īn yaml sau altceva. Dar asta este chemarea ta, oricum.