3

Is it possible to create a global listener for an exception in Ruby?

I want to catch all exceptions in my script for StateMachine::InvalidTransition so my application can respond with sending an email with the error.

Normally in Ruby, a rescue block is preceded by begin, but I want to have a central listener method that will catch all exceptions for the above mentioned exception.

Is this possible at all?

I really don't want to place

begin
    # Do some stuff
rescue StateMachine::InvalidTransition => exception
    # Send error in email message
end 

inside every single event I have in my state_machine.

I want something similar to set_exception_handler() in PHP.

4

3 回答 3

1

是的,可以为异常创建全局侦听器。这里有两种方法:

1.at_exit$!

at_exit do
  if $!.is_a? StateMachine::InvalidTransition
    # Send error in email message
  end
end

这种方法仅作为崩溃记录器有用,因为它不能阻止您的脚本退出。

2.补丁raisefail

module PatchRaise
  def raise(err, *args)
    if defined?(err.exception) &&
      err.exception.is_a?(StateMachine::InvalidTransition)
      # Send error in email message
    else
      super(err, *args)
    end
  end

  def fail(*args)
    raise(*args)
  end
end

Object.prepend PatchRaise

这种方法可以阻止您的脚本退出,但它还有两个限制:

  • 它将捕获对raise/的所有调用fail,即使是那些可能被脚本中其他地方的begin/rescue块捕获的调用。
  • 由于它依赖于重写 Rubyraisefail方法,因此不会捕获任何由原生 Ruby 核心代码或 C 扩展(例如,ZeroDivisionError1/0表达式引发)生成的异常。
于 2018-03-07T02:24:09.013 回答
-2

您可以将所有内容包装在 begin/rescue/end 中。像这样:

begin
    class Sheep
        def self.raise_me
             raise
        end
    end
    Sheep.raise_me
rescue
    p 'caught!'
end

我只是不确定你是否愿意

于 2013-02-26T13:23:54.390 回答
-2

你看过 Errbit 的来源吗?这可能具有您正在寻找的功能。

错误

就个人而言,我相信你应该大量失败并且有办法处理你的反应(在肉类空间)而不是聪明地恢复。那样拉的头发太多了。:-)

此外,这对您来说也可能是一个很好的参考。

出色的红宝石书

祝你好运!

更新:2017 年 1 月 23 日

我不知道为什么这最近被否决了。我仍然支持在生产中“大规模失败”并使用其他系统处理响应,这可能与聪明的 Ruby 主义者的货物崇拜背道而驰,但在生产中,这通常是这样做的。主要是因为当你开始在野外使用其他人的生产代码时,它会缺乏测试/规范,并且由于经理压住开发人员的脖子或由于任意的截止日期而主要是动态组成的。

IMO 最好不要太巧妙地处理错误,即一些全局 catch 方法可以在遍历异常路径时保持您的应用程序正常运行。这会导致您的系统中出现静默错误,您甚至可能永远不会意识到这些错误,并且您永远不会获得良好的 TDD 代码覆盖率。全局捕获错误对于保持正常运行时间非常有用,但会阻止您了解系统中正在发生的事情。如果您实现了良好的集成测试代码覆盖率,这应该不是问题。

另外,我遇​​到过这个 gem,Contracts,因为它是用良好的代码覆盖率编写的,这将帮助您消除与代码覆盖率差和随机返回相关的异常。

更新:2017 年 3 月 8 日

我坚持我之前的更新,这解决了最重要的问题,即如何实现“侦听”红宝石应用程序中的异常的东西。

有时你问一个问题,答案是切题的,即有更好的方法。Stack Overflow 是关于利用他人的经验。打高尔夫球有其一席之地,但大多数时候是不必要的。

Errbit 是一个基于开源 Airbrake API 和 Rails 的开源异常捕获器,可以相当快地启动并提供比手动编写解决方案更多的选项。所以驳回它是错误的IMO。

关于 Exceptional Ruby Book 是一个无关紧要的资源,因为它要花钱。在我看来,作者要求为他们投入时间创作并为您的工具集增加价值的作品付费是完全可以接受的。如果这本书的价格对您来说太高了,请向您当地的图书馆索取一份副本,这就是它们存在的原因。如果失败,请联系 Avdi,或许可以达成协议。

于 2013-02-26T13:34:52.760 回答