是否可以在Ruby中为异常创建全局侦听器?
我想在我的脚本中捕获StateMachine :: InvalidTransition中的所有异常,以便我的应用程序可以通过发送包含错误的电子邮件进行响应。
通常在Ruby中,一个急救块前面是begin,但是我希望有一个中央监听器方法来捕获上述异常的所有异常。
这有可能吗?
我真的不想放置
begin
# Do some stuff
rescue StateMachine::InvalidTransition => exception
# Send error in email message
end
我在state_machine中的每一个事件中都有。
我想在PHP中使用类似于 set_exception_handler()的东西。
答案 0 :(得分:1)
是的,可以为异常创建全局侦听器。这有两种方法:
at_exit
和$!
:at_exit do
if $!.is_a? StateMachine::InvalidTransition
# Send error in email message
end
end
此方法仅用作崩溃记录器,因为它无法阻止您的脚本退出。
raise
和fail
: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
块捕获的来电。raise
和fail
方法,因此不会捕获由本机Ruby-core代码或C扩展(例如,ZeroDivisionError
生成的任何异常。 {1}}表达)。答案 1 :(得分:-2)
您可以将所有内容包装在begin / rescue / end中。像这样:
begin
class Sheep
def self.raise_me
raise
end
end
Sheep.raise_me
rescue
p 'caught!'
end
我只是不确定你想要。
答案 2 :(得分:-2)
你看过Errbit的来源了吗?这可能具有您正在寻找的功能。
就我个人而言,我相信你应该大规模失败并有办法处理你的反应(在肉类空间),而不是巧妙地恢复。这样的头发拉得太多了。 :-)
此外,这也可能是一个很好的参考。
祝你好运!
更新:1/23/2017
我不知道为什么最近这个被低估了。我仍然坚持在生产中“大规模失败”并处理与其他系统的反应,这可能与聪明的Rubyist的货物崇拜背道而驰,但在生产中,这是通常的方式。主要是因为当你开始在其他人的生产代码中开始工作时,它将缺乏测试/规格,并且由于经理呼吸开发人员的脖子或因为任意的截止日期而主要是动态组合。
IMO最好不要过于巧妙地处理错误,即一些全局捕获方法可以在遍历异常路径时保持应用程序正常运行。这会导致系统中的静默错误,您甚至可能从未意识到这些错误,并且您从未获得良好的TDD代码覆盖率。全局捕获错误对于一致的正常运行时间非常有用,但会阻止您了解系统中发生的情况。如果您实现良好的集成测试代码覆盖率,这应该不是问题。
另外,我遇到过这个gem Contracts,因为这是写的,并且再次提供良好的代码覆盖率,这将有助于消除与代码覆盖率差和随机返回相关的异常。
更新:3/8/2017
我支持我之前的更新,这解决了一个首要问题,即如何实现能够“监听”ruby应用程序中的异常的内容。
有时你问一个问题,答案是切线的,即有更好的方法。 Stack Overflow是关于利用其他人的经验。代码打高尔夫有它的位置,但大多数时候是不必要的。
Errbit是一个基于开源Airbrake API和Rails的开源异常捕获器,它可以相当快地站起来并提供比手动编码解决方案更多的选项。所以解雇它是错误的IMO。
关于特殊Ruby Book是一种不相关的资源,因为它需要花钱。在我看来,作者要求为他们花时间创作并为你的工具集增加价值的作品付费是完全可以接受的。如果这本书的价格对你来说太苛刻,请要求你当地的图书馆获得一份副本,这就是它们存在的原因。如果失败,请联系Avdi,也许可以达成协议。