Samenvoegen hashes in YAML conf bestanden
YAML is heel handig voor het schrijven van configuratiebestanden. Primair voordeel is dat, het leest als tekstbestand. Dit werkt echt goed als je config bestand is plat (geen hiërarchie) en heeft geen herhalingen.
Als uw configuratie bestand herhalingen dan is het zinvol deze te scheiden van die elementen en ze opnieuw te gebruiken. Wat ik bedoel is dit - laten we zeggen dat je je config bestand ziet er als volgt uit:
ontwikkeling: input_location: common_input output_location: dev_location mail: smtp_server: uw_server login: your_login wachtwoord: top_secret productie: input_location: common_input output_location: dev_location mail: smtp_server: uw_server login: your_login wachtwoord: top_secret
Ervan uitgaande dat bovenstaande code in / tmp / test.yml hier is hoe je kunt lezen in Python en Ruby
$cat readyml.py
#! / Usr / bin / env python van pprint import pprint als pp # In debian moet python-yaml te installeren van yaml import belasting, load_all, dump hash = belasting (open ("/ tmp / test.yml ')) pp (hash ['ontwikkeling'])
$ cat readyml.rb
#! / Usr / bin / env ruby require 'pp' hash = YAML :: load (File.open ('/ tmp / test.yml'). lezen) pp hash ['ontwikkeling']
Hier is een handige one-liner voor Ruby versie
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' of u kunt hetzelfde proberen in irb of python console.
Merk op dat in het bovenstaande stukje code, alles is anders dan uitvoerlocatie hetzelfde is in ontwikkeling en productie deel. Dit is waar yml node identifier komt te redden is. Idee is simpel beschikken over een set van standaard waarden en ze op andere plaats te overschrijven.
Je zou kunnen trek het uit elkaar als volgt:
standaard: & defaults input_location: common_input output_location: dev_location mail: SENDER_NAME: afzender smtp_server: uw_server login: your_login wachtwoord: top_secret ontwikkeling: <<: * Standaard productie: <<: * Standaard output_location: prod_location
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$
Geweldig, het werkt (tm)!.
Ongetwijfeld hebben we geruild enige duidelijkheid voor een beetje magie. Hier is een kleine uitleg: &, * en <<: & dat is ankertag kan worden opgevat als node identifier, * is knooppunt referentie-en <<: staat voor hash samenvoegen.
Voor meer details zie ofwel yaml specs of wikipedia
Tot nu toe zo goed, maar er is hier een vangst, deze hash fuseert zijn niet recursief. Wat het betekent is dit: stel dat u verschillende afzender naam hebben voor de post in twee omgevingen, kunt u in de verleiding komen het volgende doen:
standaard: & defaults input_location: common_input output_location: dev_location mail: SENDER_NAME: afzender smtp_server: uw_server login: your_login wachtwoord: top_secret ontwikkeling: <<: * Standaard mail: SENDER_NAME: sender_dev productie: <<: * Standaard output_location: prod_location mail: SENDER_NAME: sender_prod
Laten we bekijken
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
nil
$
Oeps, er ging iets mis, probleem zoals hierboven vermeld is dat de hash samenvoegen niet recursief is en bij het samenvoegen van deze vervangen mail in gebreke per post van de productie die op een sleutel heeft. Oplossing / werk in de buurt is om uitgerold nog een niveau:
common_settings: & common_settings input_location: common_input output_location: dev_location mail_defaults: & mail_defaults SENDER_NAME: afzender smtp_server: uw_server login: your_login wachtwoord: top_secret standaard: & defaults << * Common_settings mail: << * Mail_defaults ontwikkeling: <<: * Standaard productie: <<: * Standaard mail: << * Mail_defaults SENDER_NAME: sender_prod
Laten we controleer opnieuw
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$
Heb je zeggen dat je nog een niveau van nesting, goed je kan zeker uitrollen nog een niveau, maar dan wordt het een puinhoop. Dus, als je niet probeert om oplossing voor Torens van Hanoi in een conf bestand te schrijven, is het beter om conf bestand restucture dan graven in yaml of iets anders. Maar dat is uw oproep toch.



































