在YAML conf文件合併哈希

2009年7月31日,由prashant · 評論
提起下: 技術

YAML編寫的配置文件是相當方便。 主要優點是,它像文本文件中讀取。 這作品真的很好,如果你的配置文件是平坦的(沒有等級),並沒有重複。
如果您的配置文件,然​​後重複分離出這些元素和重用它們是有意義的。 我的意思是 - 讓我們說你的配置文件看起來像這樣:

 發展:
   input_location:common_input
   output_location:dev_location
  郵箱:
     smtp_server:您的服務器
    登錄:your_login
    密碼:top_secret
生產:
   input_location:common_input
   output_location:dev_location
  郵箱:
     smtp_server:您的服務器
    登錄:your_login
    密碼:top_secret 

假設上面的代碼在/ tmp / test.yml這裡是你如何可以閱讀 Python和Ruby
$cat readyml.py

 #!/ USR / BIN / ENV蟒蛇
 pprint為 PP進口 pprint
 #需要在Debian安裝 python - YAML
從 YAML進口負載,load_all,轉儲
哈希=負荷(打開(“/ tmp目錄 / test.yml”))
 PP(哈希['發展']) 


$ cat readyml.rb

  #!/ USR / BIN / ENV紅寶石
需要“PP”
哈希= YAML:負載(File.open(“/ tmp目錄 / test.yml”)閱讀。)
 PP哈希“發展”] 

這裡是一個方便的Ruby版本班輪
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]'或您可以嘗試在irb或Python控制台相同。

請注意,在上面的代碼片斷,一切都以外的輸出位置是在開發和生產的部分相同。 這是YML節點標識符來救援。 想法很簡單,他們在不同的地方有一個默認值的設置和覆蓋。
你可以把它拆開如下:

 默認值:與默認值
   input_location:common_input
   output_location:dev_location
  郵箱:
     SENDER_NAME:發送方
     smtp_server:您的服務器
    登錄:your_login
    密碼:top_secret
發展:
   <<:*默認值
生產:
   <<:*默認值
   output_location:prod_location 


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

大,它的工作原理(TM)。
可以說,我們交易的一些清晰的魔術位。 這裡是一個小的解釋:&,*和<<:&這是可以理解為節點標識符,錨標記,*是節點的引用和<<:代表哈希合併。

更多細節見或者YAML規格維基百科
到目前為止好,但這裡有一個陷阱,這些哈希合併不是遞歸的。 它的意思是這樣的:比方說,你要在兩個環境不同的郵件發件人的姓名,你可能會做到以下幾點:

 默認值:與默認值
   input_location:common_input
   output_location:dev_location
  郵箱:
     SENDER_NAME:發送方
     smtp_server:您的服務器
    登錄:your_login
    密碼:top_secret
發展:
   <<:*默認值
  郵箱:
     SENDER_NAME:sender_dev
生產:
   <<:*默認值
   output_location:prod_location
  郵箱:
     SENDER_NAME:sender_prod 

讓檢查

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

糟糕,出事了,上面提到的問題是不是遞歸哈希合併,並在合併時,它取代默認的郵件郵件只有一個關鍵的生產。 解決方案/變通方法是展開一個多水平:

  common_settings:&common_settings
 input_location:common_input
 output_location:dev_location
 mail_defaults:&mail_defaults
  SENDER_NAME:發送方
   smtp_server:您的服務器
  登錄:your_login
  密碼:top_secret

默認值:與默認值
   <<:* common_settings
  郵箱:
     <<:* mail_defaults
發展:
   <<:*默認值
生產:
   <<:*默認值
  郵箱:
     <<:* mail_defaults
     SENDER_NAME:sender_prod

讓我們再次檢查

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

你說你有一個級別的嵌套,你可以展開一個多水平,但隨後成為一個爛攤子。 所以,如果你不嘗試寫河內塔在conf文件的解決方案,它是更好地restucture conf文件,比挖成YAML或別的東西。 但是,這無論如何是您的通話。