问题
I have a module in which I am performing all of my encryption/decryption tasks for a project. I would like to catch any OpenSSL::Cipher::CipherError
exceptions that occur in this module so that I can handle them.
Is it possible to do something like
rescue_from OpenSSL::Cipher::CipherError, :with => :cipher_error
inside of a module?
回答1:
I've investigated a little and came with a solution. You said you have a module in which you do your encryption. I'm guessing that module represents a singleton. My solution, however, requires you have an instance instead.
class Crypto
def self.instance
@__instance__ ||= new
end
end
Extract encryption behavior in a module.
module Encryptable
def encrypt
# ...
end
def decrypt
# ...
end
end
Create a new module that handles exceptions.
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
So now you can use the newly defined handle_known_exceptions
inside your Crypto
. This is not very convenient because you haven't gained much. You still have to call the exception handler inside every method:
class Crypto
include ExceptionHandler
def print_bunnies
handle_known_exceptions do
File.open("bunnies")
end
end
end
No need to do this if we define a delegator that does that for us:
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
Completely override the initialization of Crypto
, to use the delegator instead.
class Crypto
include Encryptable
def self.new(*args, &block)
CryptoDelegator.new(super)
end
def self.instance
@__instance__ ||= new
end
end
And that's it!
来源:https://stackoverflow.com/questions/16567243/rescue-all-errors-of-a-specific-type-inside-a-module