Merging-Hashes in yaml conf-Dateien
YAML ist sehr nützlich für das Schreiben von Konfigurationsdateien. Primärer Vorteil ist, dass, liest es wie Text-Datei. Das funktioniert wirklich gut, wenn deine config-Datei ist flach (keine Hierarchie) und hat keine Wiederholungen.
Wenn Ihre Konfigurationsdatei hat Wiederholungen dann macht es Sinn zu trennen diejenigen Elemente und wiederverwendet werden. Was ich meine ist diese - sagen wir mal du deine config-Datei wie folgt aussieht:
Entwicklung: input_location: common_input output_location: dev_location mail: smtp_server: Ihr_Server login: your_login Kennwort: top_secret Produktion: input_location: common_input output_location: dev_location mail: smtp_server: Ihr_Server login: your_login Kennwort: top_secret
Angenommen obigen Code in / tmp / test.yml hier, wie Sie in Python und Ruby zu lesen
$cat readyml.py
#! / Usr / bin / env python von pprint Import pprint als pp # In debian müssen python-yaml installieren von yaml import laden, load_all, dump hash = load (open ('/ tmp / test.yml')) pp (hash ["Entwicklung"])
$ cat readyml.rb
#! / Usr / bin / env ruby require 'pp' hash = YAML:: load (File.open ('/ tmp / test.yml') zu lesen.) pp hash ["Entwicklung"]
Hier ist eine praktische Einzeiler für die Ruby-Version
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' oder Sie können das gleiche in irb oder Python-Konsole ausprobieren.
Beachten Sie, dass in den obigen Code-Schnipsel, alles andere als Ausgang Standort gleichen in der Entwicklung und Produktion Teil ist. Dies ist, wo yml Knoten-ID kommt zu retten. Idee ist einfach eine Reihe von Standardwerten und überschreiben sie an anderer Stelle.
Sie ziehen konnte es auseinander wie folgt:
Standardeinstellungen: & defaults input_location: common_input output_location: dev_location mail: sender_name: Absender smtp_server: Ihr_Server login: your_login Kennwort: top_secret Entwicklung: <<: * Defaults Produktion: <<: * Defaults output_location: prod_location
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$
Große, es funktioniert (tm)!.
Wohl haben wir gehandelt Klarheit für ein bisschen Magie. Hier eine kleine Erläuterung: &, * und <<: & das Anker-Tag als Knoten-ID verstanden werden kann, ist * Knoten-Referenz und <<: steht für Hash verschmelzen.
Weitere Details finden Sie entweder yaml specs oder wikipedia
So weit so gut, aber es gibt einen Haken hier, sind diese Hash geht nicht rekursiv. Was es bedeutet, ist dies: Angenommen, Sie möchten verschiedene Absender-Namen für E-Mail in beiden Umgebungen haben, könnten Sie versucht, die Folgendes leistet:
Standardeinstellungen: & defaults input_location: common_input output_location: dev_location mail: sender_name: Absender smtp_server: Ihr_Server login: your_login Kennwort: top_secret Entwicklung: <<: * Defaults mail: sender_name: sender_dev Produktion: <<: * Defaults output_location: prod_location mail: sender_name: sender_prod
Lets prüfen
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
nil
$
Hoppla, ist etwas schief gelaufen, Problem wie oben erwähnt ist, dass die Hash-merge nicht rekursiv ist und während der Zusammenführung es ersetzt mail des Ausfalls mail der Produktion, die nur einen Schlüssel hat. Lösung / Umgehung ist zu entrollen eine weitere Ebene:
common_settings: & common_settings input_location: common_input output_location: dev_location mail_defaults: & mail_defaults sender_name: Absender smtp_server: Ihr_Server login: your_login Kennwort: top_secret Standardeinstellungen: & defaults <<: * Common_settings mail: <<: * Mail_defaults Entwicklung: <<: * Defaults Produktion: <<: * Defaults mail: <<: * Mail_defaults sender_name: sender_prod
Lets prüfen Sie erneut
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$
Haben Sie sagen, Sie haben eine weitere Ebene der Verschachtelung, gut man kann definitiv entrollen eine weitere Ebene, aber dann wird es ein Durcheinander. Also, wenn Sie nicht versuchen, Lösung der Türme von Hanoi in einer conf-Datei zu schreiben, ist es besser, conf-Datei als Graben in yaml oder etwas anderes restucture. Aber das ist Ihr Anruf trotzdem.



































