Hash Îmbinarea în fişierele conf yaml

31 iulie 2009 de Prashant
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.

Comentarii

  • Complet 453-pagina de document enumeră, de asemenea, domenii potenţiale pentru
    de consolidare, inclusiv privatizarea preluare gunoi, fuzionarea oraş şi
    Wayne County departamentele de sănătate şi de parteneriatul cu şcolile publice din Detroit pe
    recreere. Propunerea nu a inclus nici un ...

  • O persoana familiara cu acordul a declarat cele două părţi sunt încă hashing un nume pentru o companie fuzionată. Dar, această persoană a spus o idee fiind luat în considerare este alegerea unui nume care nu are cuvântul "Deutsche" sau acronimul "NYSE", în ea. ...

  • Da enervant nu îmbinare recursiv. Am fost capabil sa faca o soluţie în biblioteca mea balphp.

comentarii blog powered by Disqus