Excepciones de rescate para todos los métodos en una clase

Básicamente, este es el código normal:

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 

Pero en PHP, puedo usar el método mágico __call para crear una clase abstracta, de esta forma:

 class FooAbstract { public function __call($name, $args) { # Try catch in here... } } class Foo extends FooAbstract { public function hi() { # Code with try catch... } } 

¿Cómo puedo usar el método __call en la clase Ruby?

No estoy seguro de lo que quieres lograr aquí, pero el equivalente de Ruby de __call() de PHP es method_missing .

De forma predeterminada, cuando intenta llamar a un método no existente, obtendrá una excepción. Pero si quieres implementar una “clase abstracta”. También puede probar esta solución: https://stackoverflow.com/a/512505/185870

Podría definir un módulo que, cuando se incluye, define un gancho method_added que envuelve todos los métodos nuevos dentro de un bloque 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 

Esto sería usado como:

 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 

Esto daría como resultado:

 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 `
' reraising..

No estoy seguro si es una buena idea.

Podría sacar la parte method_added y se vería algo así como:

 class Foo with_rescue def foofoo(arg) puts arg.inspect end end 

(Puede simplemente cambiar el nombre de handle_method_exceptions a with_rescue y eliminar todos los trucos de @__ignoring_added_methods y el método method_added y debería funcionar como se describe).