Ruby Oneline Rescue

23

最近我学到一个技巧,就是在代码的某一行使用rescue,以防这一行出现错误(参见http://www.rubyinside.com/21-ruby-tricks-902.html的第21条)。我有些代码原本是这样的:

if obj['key'] && obj['key']['key2'] && obj['key']['key2']['name']
  name = obj['key']['key2']['name']
else
  name = ''
end

通过使用rescue 方法,我相信我可以将那段代码改写成类似于下面的形式:

name = obj['key']['key2']['name'] rescue ''
如果在访问哈希表的任何级别上抛出nil异常,它应该被rescue捕获并给我返回''(这是我想要的)。如果需要,我还可以选择将name设置为 nil 。这样做是否存在已知的危险?我之所以这样问是因为这看起来太美好了。我有很多丑陋的代码,我希望能摆脱掉,就像第一个代码示例那样。

对于特定的用途,内联 rescue 是安全的。但是,在方法调用的末尾使用它时要非常小心,因为其他原因可能会引发异常,例如 I/O 错误或缺少数据库信息。调试这些情况真的非常困难,可能会让你发疯。 - the Tin Man
2个回答

17

看起来不错!但它会影响你的性能。根据我的经验,当触发时rescue要慢得多,并且当它没有被触发时略微变慢。在所有情况下,if是更快的选择。另一个需要考虑的事情是,异常并不应该被期望,而你这样写代码就有可能发生异常。将哈希嵌套得如此深可能是重构的信号。


哈希值来自返回嵌套的 JSON 数据的 Web 服务。由于该服务经常将嵌套元素留空,因此我必须一路检查 nil 值。 - Jimmy Z
如果是这种情况,我建议您使用一个 gem 来增强您的哈希表,使您的代码更易读:https://github.com/intridea/hashie。 - Leonel Galán
特别是 Mash(https://github.com/intridea/hashie#mash),查看多级测试的示例,它可能不比 ifs 更快,但会改善您的代码! - Leonel Galán

14

现在可以使用 Ruby 2.3 的 dig方法 来实现此特定示例。

name = obj.dig 'key', 'key2', 'name'

这将安全地访问obj['key']['key2']['name'],如果任何步骤失败则返回nil。

(通常建议仅在遇到真正的、未预料到的错误时使用异常,尽管在像这样的示例中如果语法使其笨重也是可以理解的。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接