【问题标题】:Test Ruby multi dimensional hash [duplicate]测试Ruby多维哈希[重复]
【发布时间】:2012-06-18 21:04:36
【问题描述】:

可能重复:
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'

问题是,'level2' 可能根本不存在,所以接收者是 nil。

在 PHP 中,您可以在前面加上一个“@”来抑制错误。

在 Ruby 中,我必须将检查包装在 begin-rescue 块中。

有没有类似 PHP 的快速解决方案?

【问题讨论】:

标签: ruby


【解决方案1】:
do_x if cat['level1']['level2']['level3'] != 'value' rescue nil

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

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

话虽如此,为什么不消除嵌套并完全避免这个问题呢?

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

【讨论】:

    【解决方案2】:

    您可以在 nil 上重新定义 [],使其在运行代码之前按照您想要的方式运行:

    class NilClass
      def[](key)
        nil
      end
    end
    

    【讨论】:

    • 虽然这可以在这里工作,但我强烈建议您不要这样做,因为这将非常有效地隐藏真正的错误并使调试任何足够复杂的应用程序成为一场噩梦。发生故障时出错通常是一件好事:)
    【解决方案3】:
    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
    

    【讨论】:

      【解决方案4】:

      我会使用 try 方法而不是救援。 do_x if cat['level1'].try(:[], 'level2').try(:[], 'level3') 所以如果 do_x 引发异常,它不会被救出,你会真正看到 do_x 内部是否有问题

      【讨论】:

        猜你喜欢
        • 2015-01-20
        • 2011-07-31
        • 2011-12-28
        • 2021-11-03
        • 1970-01-01
        • 2018-02-05
        • 2012-09-06
        • 1970-01-01
        • 2015-06-13
        相关资源
        最近更新 更多