【问题标题】:Catching exceptions while using an external gem在使用外部 gem 时捕获异常
【发布时间】:2013-05-03 09:56:44
【问题描述】:

我编写了一个使用外部 ruby​​ gem 的程序。由于我对此进行了许多不同的操作,因此我希望能够全面挽救和处理异常,而不是每次调用方法时都执行它。

最好的方法是什么?
我应该编写自己的方法来简单地调用外部 gem 并挽救异常吗?或者是否有另一种方法来执行诸如“每当程序中的任何地方出现这种类型的异常时,都以这种方式处理”?

我知道如果我编写了外部 gem 代码,我可以添加这样的错误处理,但这是不可行的。

【问题讨论】:

    标签: ruby twitter gem rescue


    【解决方案1】:

    对此的基本答案可能是包装您正在使用的类; Ruby 为执行此操作提供了很大的灵活性,因为它具有 method_missing 和一个非常动态的类环境。这是一个例子(可能有也可能没有致命缺陷,但展示了原理:

    # A Foo class that throws a nasty exception somewhere.
    class Foo
      class SpecialException < Exception; end
    
      def bar
        raise SpecialException.new("Barf!")
      end
    end
    
    # This will rescue all exceptions and optionally call a callback instead
    # of raising.
    class RescueAllTheThings
      def initialize(instance, callback=nil)
        @instance = instance
        @callback = callback
      end
    
      def method_missing(method, *args, &block)
        if @instance.respond_to? method
          begin
            @instance.send(method, *args, &block)
          rescue Exception => e
            @callback.call(e) if @callback
          end
        else
          super
        end
      end
    end
    
    # A normal non-wrapped Foo. Exceptions will propagate.
    raw_foo = Foo.new
    
    # We'll wrap it here with a rescue so that we don't exit when it raises.
    begin
      raw_foo.bar
    rescue Foo::SpecialException
      puts "Uncaught exception here! I would've exited without this local rescue!"
    end
    
    # Wrap the raw_foo instance with RescueAllTheThings, which will pass through
    # all method calls, but will rescue all exceptions and optionally call the
    # callback instead. Using lambda{} is a fancy way to create a temporary class
    # with a #call method that runs the block of code passed. This code is executed
    # in the context *here*, so local variables etc. are usable from wherever the
    # lambda is placed.
    safe_foo = RescueAllTheThings.new(raw_foo, lambda { |e| puts "Caught an exception: #{e.class}: #{e.message}" })
    
    # No need to rescue anything, it's all handled!
    safe_foo.bar
    
    puts "Look ma, I didn't exit!"
    

    使用非常通用的包装类版本是否有意义,例如上面的 RescueAllTheThings 类,或者更具体的你试图包装的东西,很大程度上取决于上下文和你的具体问题'正在寻找解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-13
      • 2023-03-28
      • 1970-01-01
      • 2011-11-27
      • 2017-07-04
      • 1970-01-01
      相关资源
      最近更新 更多