【问题标题】:Ruby catch all exception classRuby 捕获所有异常类
【发布时间】:2018-04-21 02:58:40
【问题描述】:

我怎样才能像这样捕获 ruby​​ 类中的所有异常:

class ServiceException
rescue => e
   puts 'Error!!!'
end

class ServiceA < ServiceException
   def say_hello
      error_code_here
   end
end

ServiceA.new.say_hello
# => Error!!!

【问题讨论】:

    标签: ruby exception


    【解决方案1】:

    好的,所以我设法通过一些元编程来实现这一点。首先定义这个模块:

    module MetaprogrammingStuff
    
      def rescue_all_methods(klass, *errors_to_rescue, &blk)
        patch_all_methods(klass) do |orig_method, *args, &caller_blk|
          begin
            orig_method.call *args, &caller_blk
          rescue *errors_to_rescue => e
            blk.call e
          end
        end
      end
    
      def patch_all_methods(klass, &blk)
        patch_class_methods(klass, &blk)
        patch_instance_methods(klass, &blk)
      end
    
      def patch_class_methods(klass, &blk)
        klass.methods(false).each do |fn_name|
          orig_method = klass.method fn_name
          klass.singleton_class.send(:define_method, fn_name) do |*args, &caller_blk|
            blk.call orig_method, *args, &caller_blk
          end
        end
      end
    
      def patch_instance_methods(klass, &blk)
        klass.instance_methods(false).each do |fn_name|
          orig_method = klass.instance_method fn_name
          klass.send(:define_method, fn_name) do |*args, &caller_blk|
            blk.call orig_method.bind(self), *args, &caller_blk
          end
        end
      end
    
    end
    

    然后将其扩展为一个类并运行rescue_all_methods:

    class TestClass
      extend MetaprogrammingStuff
      def foo
        raise ArgumentError
      end
      def self.foo
        raise RuntimeError
      end
      rescue_all_methods(self, ArgumentError, RuntimeError) do |error|
        puts "#{error.class} was raised."
      end
    end
    

    在定义方法之后调用rescue_all_methods 很重要。

    您可以看到它在所有实例和类方法周围插入了一个救援块:

    TestClass.foo
    # => RuntimeError was raised.
    
    TestClass.new.foo
    # => ArgumentError was raised.
    

    它是如何工作的 - 基本上它使用 methodinstance_method 方法将方法转换为匿名函数,然后将这些方法名称重新分配给调用原始方法但使用 begin..rescue 包装器的新方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-01
      • 2011-11-09
      • 1970-01-01
      • 2022-11-23
      • 2011-08-20
      • 1970-01-01
      相关资源
      最近更新 更多