Fusionerende hashes i YAML conf filer
YAML er ganske praktisk til at skrive konfigurationsfiler. Primære fordel er, at den læser som tekstfil. Det fungerer rigtig godt, hvis din config fil er flad (ingen hierarki) og har ingen gentagelser.
Hvis din konfigurationer filen har gentagelser så giver det mening at udskille disse elementer og genbruge dem. Hvad jeg mener er dette - lad os sige, at du din config fil ser sådan her ud:
udvikling: input_location: common_input output_location: dev_location mail: smtp_server: din_server login: your_login Password: top_secret produktion: input_location: common_input output_location: dev_location mail: smtp_server: din_server login: your_login Password: top_secret
Forudsat ovenstående kode i / tmp / test.yml her er, hvordan kan du læse i Python og Ruby
$cat readyml.py
#! / Usr / bin / env python fra pprint indførsel pprint som pp # I debian nødt til at installere python-YAML fra YAML import belastning, load_all, dump hash = belastning (åben ('/ tmp / test.yml')) pp (hash ['udvikling'])
$ cat readyml.rb
#! / Usr / bin / env rubin kræver 'PP' hash = YAML :: belastning (File.open ('/ tmp / test.yml). læst) pp hash ['udvikling']
her er en handy en liner for Ruby-version
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' , eller du kan prøve det samme i IRB eller Python konsol.
Bemærk, at i ovenstående kodestykke, er alt andet end output placering er den samme i udvikling og produktion del. Det er her yml node id kommer til at redde. Ideen er enkel have et sæt standardværdier og tilsidesætter dem på andet sted.
Du kan trække det ud som følger:
standarder: og standarder input_location: common_input output_location: dev_location mail: SENDER_NAMEs: afsender smtp_server: din_server login: your_login Password: top_secret udvikling: <<: * Standard produktion: <<: * Standard output_location: prod_location
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$
Great, det virker (tm)!.
Formentlig har vi handlet lidt mere klarhed for lidt magi. Her er en lille forklaring: &, * og <<: & der er ankerkode kan forstås som node identifikator, * er node reference og <<: står for hash merge.
For flere detaljer se enten YAML specs eller wikipedia
Så langt så godt, men der er en fangst her, disse hash fusionerer ikke rekursiv. Hvad det betyder er dette: Lad os sige du vil have forskellige afsenderens navn for e-mail i to miljøer, kan du blive fristet til at gøre følgende:
standarder: og standarder input_location: common_input output_location: dev_location mail: SENDER_NAMEs: afsender smtp_server: din_server login: your_login Password: top_secret udvikling: <<: * Standard mail: SENDER_NAMEs: sender_dev produktion: <<: * Standard output_location: prod_location mail: SENDER_NAMEs: sender_prod
Lad os kontrollere
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
nil
$
Ups, noget gik galt, problem, som nævnt ovenfor er, at hash fletningen ikke er rekursiv, og samtidig lægge det erstattet post af misligholdelse af post produktion, som kun har en nøgle. Løsning / arbejde omkring at oprulle en mere niveau:
common_settings: & common_settings input_location: common_input output_location: dev_location mail_defaults: & mail_defaults SENDER_NAMEs: afsender smtp_server: din_server login: your_login Password: top_secret standarder: og standarder <<: * Common_settings mail: <<: * Mail_defaults udvikling: <<: * Standard produktion: <<: * Standard mail: <<: * Mail_defaults SENDER_NAMEs: sender_prod
Lad os se igen
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$
Sagde du du har en større niveau af nesting, godt du kan helt sikkert oprulle en mere lige, men så bliver det noget rod. Så, hvis du ikke forsøger at skrive løsning tårne i Hanoi i en conf-fil, er det bedre at restucture conf fil end at grave i YAML eller noget andet. Men det er dit opkald alligevel.



































