基本上,这是正常的代码:
class Foo
def hi
# your code here....
rescue => e
# Raise error here
end
def hello
# your code here...
rescue => e
# Raise error here
end
end
Run Code Online (Sandbox Code Playgroud)
但在 PHP 中,我可以使用__call魔术方法创建抽象类,如下所示:
class FooAbstract {
public function __call($name, $args) {
# Try catch in here...
}
}
class Foo extends FooAbstract {
public function hi() {
# Code with try catch...
}
}
Run Code Online (Sandbox Code Playgroud)
我如何在 Ruby 类中使用 __call 方法???
您可以定义一个模块,该模块在包含时定义一个method_added将所有新方法包装在begin..rescue块内的钩子:
require 'set'
module ExceptionHandler
def self.included(klass)
super
klass.send(:extend, ClassMethods)
end
module ClassMethods
def exception_handler(&block)
@__exception_handler = block.to_proc
end
def handle_exception(exception)
defined?(@__exception_handler) ? @__exception_handler.call(exception) : super
end
def handle_method_exceptions(method_name)
old_method = instance_method(method_name)
return if (@__hooked_methods ||= Set.new).include?(method_name)
@__ignoring_added_methods = true # avoid infinite define_method/method_added loop
define_method method_name do |*args, &block|
begin
old_method.bind(self).(*args, &block)
rescue => ex
self.class.handle_exception(ex)
end
end
@__ignoring_added_methods = false
@__hooked_methods << method_name
end
def method_added(method_name)
super
unless @__ignoring_added_methods
handle_method_exceptions(method_name)
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
这将像这样使用:
class Foo
include ExceptionHandler
exception_handler do |exception|
puts "Catched an exception:"
puts "---------------------"
puts "Exception class: #{exception.class}"
puts "Message: #{exception.message}"
puts "Backtrace:"
puts exception.backtrace.join("\n ")
puts
puts "reraising.."
puts
raise exception
end
def this_raises
raise "somebody set up us the bomb"
end
end
Foo.new.this_raises
Run Code Online (Sandbox Code Playgroud)
这将输出:
Catched an exception:
---------------------
Exception class: RuntimeError
Message: somebody set up us the bomb
Backtrace:
errorhandler.rb:62:in `this_raises'
errorhandler.rb:26:in `call'
errorhandler.rb:26:in `block in handle_exceptions'
errorhandler.rb:67:in `<main>'
reraising..
Run Code Online (Sandbox Code Playgroud)
我不确定这是否是一个好主意。
你可以把这个部分拿出来method_added,它看起来像这样:
class Foo
with_rescue def foofoo(arg)
puts arg.inspect
end
end
Run Code Online (Sandbox Code Playgroud)
(您只需将其重命名handle_method_exceptions为with_rescue并删除所有@__ignoring_added_methods技巧和method_added方法,它应该按描述的方式工作)。
| 归档时间: |
|
| 查看次数: |
3369 次 |
| 最近记录: |