在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或别的东西。 但是,这无论如何是您的通话。