我经常为应用程序的大型配置创建 YAML 生成器。为了维护,我需要对字段进行排序。
我在按排序顺序生成 YAML 时使用的解决方案是根据需要添加键以将它们放入正确的散列或子散列中。然后我通过对键/值对进行排序来创建一个新的哈希并to_yaml
对其进行操作。
对哈希进行排序是没有意义的,但是在让 YAML 让它工作之前对要输出的临时哈希进行排序并产生更容易维护的文件。
require 'yaml'
some_hash = {
'z' => 1,
'a' => 3
}
puts some_hash.to_yaml
哪个输出:
---
z: 1
a: 3
在创建 YAML 输出之前对其进行排序:
puts Hash[some_hash.merge('x' => 2).sort_by{ |k, v| k }].to_yaml
输出:
---
a: 3
x: 2
z: 1
而不是puts
使用File.write
或嵌入该行到传递给的块中File.open
。
关于 YAML 文件中的注释:YAML 不支持以编程方式向发出的输出添加注释。注释适用于人类,#
不能映射到 Ruby 变量或对象。可以这样想:如果我们从一个名为的文件中的这个 YAML 开始test.yaml
:
---
# string
a: 'fish'
# array
b:
- 1
- 2
# hash
c:
d: 'foo'
e: 'bar'
# integer
z: 1
并加载它:
require 'pp'
require 'yaml'
obj = YAML.load_file('test.yaml')
pp obj
我obj
看起来像:
{"a"=>"fish", "b"=>[1, 2], "c"=>{"d"=>"foo", "e"=>"bar"}, "z"=>1}
没有返回“注释”对象,并且 Ruby 中不存在任何适合散列的对象,这些对象存在于 YAML 规范中。我们可以随意拼凑出一个我们称为 Comment 的类,并尝试将其作为键嵌入到对象中,但 YAML 不会接受它作为注释,因为规范不允许这样做。它会将其定义为 Ruby 类并将其重新创建为该类,但不会显示为#
注释:
require 'yaml'
class Comment
def initialize(some_text)
@comment = "# #{some_text}"
end
end
some_hash = {
'a' => 1,
Comment.new('foo') => 'bar',
'z' => 'z'
}
puts some_hash.to_yaml
输出:
---
a: 1
? !ruby/object:Comment
comment: ! '# foo'
: bar
z: z
当我在发出的 YAML 配置中需要注释时,我会手动调整它们以便稍后添加它们。对于您想要做的事情,而不是进行任何手动调整,我建议您使用可以在文档中扫描的更多助记符或唯一变量名称。您甚至可以放入除了充当占位符之外不提供任何有价值的东西的虚拟条目:
require 'yaml'
some_hash = {
'a' => 1,
'__we_are_here__' => '',
'b' => 2,
'__we_are_now_here__' => '',
'z' => 'z'
}
puts some_hash.to_yaml
生成一个 YAML 文件,如:
---
a: 1
__we_are_here__: ''
b: 2
__we_are_now_here__: ''
z: z
至于将密钥插入哈希,我可能会稍微重组我的“密钥链”,以显示我想要插入它的路径以及新密钥的名称。同样,在保存 YAML 之前,我会依靠排序来确保事情的顺序正确:
require 'pp'
# this changes the incoming hash
def insert_embedded_hash_element(hash, key_path, new_value)
keys = key_path.split('.')
new_key = keys.pop
sub_hash = hash
keys.each do |k|
sub_hash = sub_hash[k]
end
sub_hash[new_key] = new_value
end
# the sub-hash to insert into + new key name
insert_key = 'nested.key2'
insert_value = 'new_value'
hash = {
"some_key" => "value",
"nested" => {
"key1" => "val1",
"key3" => "val2"
}
}
insert_embedded_hash_element(hash, insert_key, insert_value)
pp hash
导致:
{"some_key"=>"value",
"nested"=>{"key1"=>"val1", "key3"=>"val2", "key2"=>"new_value"}}