2016-01-23 36 views
1

我有一个简单的函数,它需要一个JSON和'做些什么'。主要部分工作良好,但功能不仅返回我想要的,而且还有。每个循环的结果!木偶 - 自定义函数中'each'的意外结果

的代码:

module Puppet::Parser::Functions 
    newfunction(:mlh, :type => :rvalue) do |args| 

    lvm_default_hash = args[0] 
    lvm_additional_hash = args[1] 

    if lvm_additional_hash.keys.length == 1 
     if lvm_additional_hash.keys.include? 'logical_volumes' 
     # do stuff - we have only 'logical_volumes' 
     lvm_default_hash.keys.each do |key| 

      pv_array  = Hash['physical_volumes' => lvm_default_hash[key]['physical_volumes']] 
      lv_hash  = lvm_default_hash[key]['logical_volumes'] 
      new_lv_hash = lvm_additional_hash['logical_volumes'] 
      merged_lv_hash = Hash['logical_volumes' => lv_hash.merge(new_lv_hash)] 

      # this is what I want to return to init.pp 
      puts Hash[key => pv_array.merge(merged_lv_hash)] 

     end 
     end 
    end 
    end 
end 

变量在init.pp是:

$default_volume_groups = { 
'sys' => { 
    'physical_volumes' => [ 
    '/dev/sda2', 
    ], 
    'logical_volumes' => { 
    'root' => {'size' => '4G'}, 
    'swap' => {'size' => '256M'}, 
    'var' => {'size' => '8G'}, 
    'docker' => {'size' => '16G'}, 
    }, 
}, 

}

和从hieradata第二个参数:

modified_volume_groups: 
logical_volumes: 
    cloud_log: 
    size: '16G' 

init.pp我有这样的事情来测试它:

notice(mlh($default_volume_groups, $modified_volume_groups)) 

,给了我一个结果:

syslogical_volumesvarsize8Gdockersize16Gcloud_logsize16Gswapsize256Mrootsize4Gphysical_volumes/dev/sda2 
Notice: Scope(Class[Ops_lvm]): sys 

的通知之前,“长”部分是正确的结果从注意:范围():sys这是什么我不想! 我知道,这是该每个循环的结果比default_volumes_groups

lvm_default_hash.keys.each do |key| 
    # some stuff 
end 

如何阻止这种不必要的结果?它吹我的傀儡的逻辑,因为我的init.pp看到这系统而不是我想要的。

有人知道如何处理这样的问题吗?

谢谢!

+0

我倾向于认为您看到的额外文本并不是函数返回值的一部分。它看起来像调试输出描述对'notice()'的调用,而不是呈现给notice()的值的任何部分以供它打印。 –

+0

谢谢,但是我的函数如何返回两个值 - 一个来自_puts_,另一个来自_each_循环的默认值? – kamh

回答

1

我发现如何处理这个问题,但也许有人可以解释我为什么它这样:)

这不起作用(短版):

module Puppet::Parser::Functions 
    newfunction(:mlh, :type => :rvalue) do |args| 

    lvm_default_hash = args[0] 
    lvm_additional_hash = args[1] 

    if lvm_additional_hash.keys.length == 1 
     if lvm_additional_hash.keys.include? 'logical_volumes' 
     lvm_default_hash.keys.each do |key| 

      pv_array  = Hash['physical_volumes' => lvm_default_hash[key]['physical_volumes']] 
      lv_hash  = lvm_default_hash[key]['logical_volumes'] 
      new_lv_hash = lvm_additional_hash['logical_volumes'] 
      merged_lv_hash = Hash['logical_volumes' => lv_hash.merge(new_lv_hash)] 

      puts Hash[key => pv_array.merge(merged_lv_hash)] 

     end 
     end 
    end 
    end 
end 

但这个工程:

module Puppet::Parser::Functions 
    newfunction(:mlh, :type => :rvalue) do |args| 

    lvm_default_hash = args[0] 
    lvm_additional_hash = args[1] 

    # empty Hash 
    hash_to_return = {} 

    if lvm_additional_hash.keys.length == 1 
     if lvm_additional_hash.keys.include? 'logical_volumes' 
     lvm_default_hash.keys.each do |key| 

      pv_array  = Hash['physical_volumes' => lvm_default_hash[key]['physical_volumes']] 
      lv_hash  = lvm_default_hash[key]['logical_volumes'] 
      new_lv_hash = lvm_additional_hash['logical_volumes'] 
      merged_lv_hash = Hash['logical_volumes' => lv_hash.merge(new_lv_hash)] 

     # assigned value in the 'each' loop we want to return to puppet 
      hash_to_return = Hash[key => pv_array.merge(merged_lv_hash)] 

     end 

     # returned Hash - instead of previous 'puts' 
     return hash_to_return 

     end 
    end 
    end 
end 

现在我有我需要的东西!

Notice: Scope(Class[Ops_lvm]): sysphysical_volumes/de 
1

你已经得到了它 - 第一个不起作用,因为在Ruby中,块或函数的返回值是最后一次评估语​​句。在没有工作的情况下,最后评估的陈述是.each。事实证明,each评估它正在循环遍历的枚举。

一个简单的例子:

def foo 
    [1, 2, 3].each do |n| 
    puts n 
    end 
end 

如果我运行此,该函数的返回值是数组:

> foo 
1 
2 
3 
=> [1, 2, 3] 

所以,你有什么工作,因为过去的事情评估为return hash_to_return。你甚至可以去hash_to_return,它会工作。

如果你想摆脱return,并清理一下一点点(如果你正在使用Ruby 1.9或以上),你可以用更换您each行:

lvm_default_hash.keys.each_with_object({}) do |key, hash_to_return|

这是因为each_with_object评估为“对象”(在这种情况下,传入该方法的空散列,在块params中被称为hash_to_return)。如果你这样做,你可以删除return以及初始化hash_to_return = {}

希望这会有所帮助!

0

您的自定义函数具有右值类型,这意味着它需要返回值。如果您在默认情况下未指定return <something>,则您的最后一条语句隐式返回。
在上面的例子中,不正常工作第一位的,有各块中的最后一条语句:

puts Hash[key => pv_array.merge(merged_lv_hash)] 

你的第二个例子是正确的,只是因为你在每块hash_to_return设定值,然后“回归”它每块之外。不确定这是否是您希望的行为,因为上次分配的散列值(在每个块内的最后一个循环中)将是将从此函数返回的散列值。

+0

这与@kamh注释有关: 我发现了如何处理这个问题,但也许有人可以解释为什么它以这种方式工作:) –