挽救模块内特定类型的所有错误

时间:2013-05-15 14:04:54

标签: ruby-on-rails ruby-on-rails-3 exception-handling rescue

我有一个模块,我在其中执行项目的所有加密/解密任务。我想捕获此模块中出现的任何OpenSSL::Cipher::CipherError异常,以便我可以处理它们。

是否可以执行类似

的操作
rescue_from OpenSSL::Cipher::CipherError, :with => :cipher_error

在模块内部?

1 个答案:

答案 0 :(得分:8)

我已经调查了一下,并提出了一个解决方案。你说你有一个模块,你可以在其中进行加密。我猜这个模块代表一个单身人士。但是,我的解决方案要求您拥有一个实例。

class Crypto
   def self.instance
      @__instance__ ||= new
   end
end

提取模块中的加密行为。

module Encryptable
   def encrypt
      # ...
   end

   def decrypt
      # ...
   end
end

创建一个处理异常的新模块。

module ExceptionHandler
  extend ActiveSupport::Concern

  included do
    include ActiveSupport::Rescuable
    rescue_from StandardError, :with => :known_error
  end

  def handle_known_exceptions
     yield
  rescue => ex
     rescue_with_handler(ex) || raise
  end

  def known_error(ex)
    Rails.logger.error "[ExceptionHandler] Exception #{ex.class}: #{ex.message}"
  end
end

现在,您可以在handle_known_exceptions内使用新定义的Crypto。这不是很方便,因为你没有获得太多。您仍然需要在每个方法中调用异常处理程序:

class Crypto
  include ExceptionHandler

  def print_bunnies
    handle_known_exceptions do
      File.open("bunnies")
    end
  end
end

如果我们定义一个为我们这样做的委托人,则无需这样做:

class CryptoDelegator
  include ExceptionHandler

  def initialize(target)
    @target = target
  end

  def method_missing(*args, &block)
    handle_known_exceptions do
      @target.send(*args, &block)
    end
  end
end

完全覆盖Crypto的初始化,改为使用委托人。

class Crypto
  include Encryptable

  def self.new(*args, &block)
    CryptoDelegator.new(super)
  end

  def self.instance
      @__instance__ ||= new
  end
end

就是这样!