我从食谱中依赖社区领事食谱 因为我有服务器和客户端模式的领事,我想分隔名称空间 在这种情况下,我可以在我的食谱中使用以下构造:
node.default['consul']['config']['server'] = node['consul-server']['config']['server'] if node['consul-server']['config']['server']
node.default['consul']['config']['ui'] = node['consul-server']['config']['ui'] if node['consul-server']['config']['ui']
node.default['consul']['config']['ports']['http'] = node['consul-server']['config']['ports']['http'] if node['consul-server']['config']['ports']['http']
node.default['consul']['config']['ports']['https'] = node['consul-server']['config']['ports']['https'] if node['consul-server']['config']['ports']['https']
按预期方式前两行,但最后两行产生以下错误:
================================================================================
Recipe Compile Error in /tmp/kitchen/cache/cookbooks/eax-consul-cluster/recipes/default.rb
================================================================================
NoMethodError
-------------
undefined method `[]' for nil:NilClass
为什么这种情况发生在相同的构造上,它们之间的唯一区别是阵列更深一层?
答案 0 :(得分:0)
这是因为在某种程度上,[]
方法会返回nil
。例如,假设node.default['consul']
返回nil
,那么node.default['consul']['config']
会引发您看到的错误。
如果node.default
是散列哈希值的哈希值,那么对于读取值,您可以尝试Hash#dig
,例如:
h = {'a' => {'b' => 'c'} }
h.dig('a', 'b') #=> c
h.dig('x', 'y') #=> nil
要设置值,您必须确保已设置父级别。
答案 1 :(得分:0)
将其切换为if if node.read('consul-server', 'config', 'ports', 'http')
。这会以与nil
类似的方式自动检查干预密钥中的Hash#dig
。
答案 2 :(得分:0)
另一方面,由于您的命名约定恰好低于第一级,因此合并它们似乎更合适并避免所有条件,深度检查等。
例如:
# Essentially a railsesque #deep_merge!
merge_proc = Proc.new do |_k,old,new|
if old.is_a?(Hash) && new.is_a?(Hash)
old.merge(new,&merge_proc)
else
new
end
end
node.default['consul'].merge!(node['consul-server'], &merge_proc)
Hash#merge!
因为Mash
(Hash
的主厨的子类)仍然是Hash