为了集中处理我的应用程序的错误,我创建了类ErrorHandling
。此类应该记录我所有的错误,通过Slack通知我,等等。
class ErrorHandler
def self.handle_error
yield
rescue => e
log_error(e.message)
notify_via_slack(e.message)
# etc.
end
end
我需要手动将MyClass
的所有方法包装在ErrorHandler.handle_error
中,以利用中央错误处理。
class MyClass
def method1
ErrorHandler.handle_error do
raise StandardError, 'my error msg'
end
end
def method2
ErrorHandler.handle_error do
raise StandardError, 'my error msg'
end
end
end
这将不必要地污染我的代码。 我考虑过动态覆盖我的方法,因此不必手动包装它们。
class MyClass
def method1
raise StandardError, 'my error msg'
end
def method2
raise StandardError, 'my error msg'
end
instance_methods(false).each do |method_name| # instance_methods(false) => [:method1, :method2]
define_method(method_name) do
ErrorHandler.handle_error do
super()
end
end
end
end
不幸的是,此代码无法正常工作。是否可以动态覆盖MyClass
的方法?
我的目标是动态重写类的所有实例方法以利用中央错误处理,因此我不必手动修改每个方法。
感谢您的帮助!
答案 0 :(得分:3)
如果您要致电super
,则应使用Module#prepend
:
ims = instance_methods(false)
prepend(Module.new do
ims.each do |method_name|
define_method(method_name) do
ErrorHandler.handle_error { super() }
end
end
end)
答案 1 :(得分:2)
我建议您使用代理模式,该模式允许您将MyClass的任何实例注入代理,然后在代理中定义所需的任何额外行为。
这里有一个练习,教您如何创建代理:
https://github.com/edgecase/ruby_koans/blob/master/src/about_proxy_object_project.rb
最后,您会得到类似的东西
class Proxy
def initialize(target_object)
@target_object = target_object
end
def missing_method(method_symbol, *args, &block)
begin
@target_object.__send__(method_symbol, *args, &block)
rescue Exception => ex
SlackNotifier.notify(ex)
raise ex
end
end
end