2012-06-15 75 views
0

可能重复:
Is there a clean way to avoid calling a method on nil in a nested params hash?测试红宝石多维散列

是否有一个简单的方法来检查,如果在一多维散列值,而没有设置醒目的NoMethodException?

例:

do_x if cat['level1']['level2']['level3'] != 'value' 

的问题是,“(第二级)”可能根本不存在,因此接收为零。

在PHP中,你可以在前面加一个'@'来抑制错误。

在Ruby中,我将不得不将检查包裹在开始救援块中。

是否有像PHP一样的快速解决方案?

+2

多重复:http://stackoverflow.com/q/5429790/188031 – tokland

回答

1
do_x if cat['level1']['level2']['level3'] != 'value' rescue nil 

这是嵌入式rescue。问题是它可以隐藏错误,因为它可以从任何RuntimeError中解救出来。你真的应该用正确的begin - rescue块来代替:

begin 
    do_x if cat['level1']['level2']['level3'] != 'value' 
rescue NoMethodError => error 
    puts error.message 
end 

虽这么说,为什么不消除嵌套和完全避免这个问题?

class NilClass 
    def[](key) 
    nil 
    end 
end 
0

你可以这样它的行为像你想运行您的代码之前,无重新定义[]。 do_x if cat['level1'].try(:[], 'level2').try(:[], 'level3')所以如果do_x抛出一个异常不会被救出,你会真正看到,如果出现错误内do_x

+3

虽然这可能是工作在这里,我强烈建议你不要这样做,因为这将非常有效地隐藏真正的错误,并使其成为调试任何足够复杂的应用程序的噩梦。当事情破裂时发生错误通常是一件好事:) –

0
class MyHash < Hash 
    def initialize(levels=0) 
    super() 
    self.default = MyHash.new(levels-1) if levels > 1 
    end 
end 

cat = MyHash.new(3) 

cat['level1']      #=> {} 
cat['level1']['level2']   #=> {} 
cat['level1']['level2']['level3'] #=> nil 
0

我会尝试使用方法而不是救助:

do_x if cat['level1.level2.level3'] != 'value'