2013-05-15 12 views
6

Ich habe ein Modul, in dem ich alle meine Verschlüsselungs-/Entschlüsselungsaufgaben für ein Projekt durchführe. Ich möchte alle OpenSSL::Cipher::CipherError Ausnahmen fangen, die in diesem Modul auftreten, damit ich sie behandeln kann.Rette alle Fehler eines bestimmten Typs in einem Modul

Ist es möglich, so etwas wie

rescue_from OpenSSL::Cipher::CipherError, :with => :cipher_error 

innerhalb eines Moduls zu tun?

+1

sind Sie dieses Modul in einem Controller oder nicht? 'rescue_from' soll nur in Controllern verwendet werden, also würde das Machen von etwas wie diesem in einfachen alten Ruby-Objekten einige sehr schmutzige Hacks beinhalten. – shime

+0

Ah, verstanden. Danke @shime – Matt

+0

Glücklich zu helfen. Überprüfen Sie hier, wenn Sie wissen wollen, was ich mit schmutzigen Hacks meinte: http://www.simonecarletti.com/blog/2009/12/inside-ruby-on-rails-rescuable-and-rescue_from/ - Ich mag es nicht wie die Dinge aussehen, wenn man es in Ruby macht und es scheint, als würde man unnötiges Durcheinander hinzufügen. Das Extrahieren der Ausnahmebehandlung in einer eigenen Methode ist eine Möglichkeit, die Sicherheit Ihres Codes zu verbessern, der in Ihrem Szenario am besten zu passen scheint. Lesen Sie mehr darüber hier: http://avdi.org/talks/confident-code-railsconf-2011/ – shime

Antwort

7

Ich habe ein wenig untersucht und kam mit einer Lösung. Sie haben gesagt, Sie haben ein Modul, in dem Sie Ihre Verschlüsselung durchführen. Ich vermute, dass das Modul ein Singleton darstellt. Meine Lösung erfordert jedoch, dass Sie stattdessen eine Instanz haben.

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

Verschlüsselungsverhalten in einem Modul extrahieren.

module Encryptable 
    def encrypt 
     # ... 
    end 

    def decrypt 
     # ... 
    end 
end 

Erstellen Sie ein neues Modul, das Ausnahmen behandelt.

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, jetzt können Sie die neu definierte verwenden handle_known_exceptions in Ihrem Crypto. Das ist nicht sehr praktisch, weil Sie nicht viel gewonnen haben. Sie haben noch die Exception-Handler innerhalb jeder Methode aufzurufen:

class Crypto 
    include ExceptionHandler 

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

Keine Notwendigkeit, dies zu tun, wenn wir eine delegator definieren, macht das für uns:

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 

Völlig überschreiben die Initialisierung von Crypto, zu Verwenden Sie stattdessen den Delegator.

class Crypto 
    include Encryptable 

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

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

Und das war's!

+1

Holy raucht, das ist ziemlich toll - vielen Dank! Ich werde es versuchen !! – Matt

+0

Haha, das hat mich gestört, weil ich mir deine Frage ein paar Mal gestellt habe. Es hat mir so viel Spaß gemacht, damit zu spielen, also habe ich beschlossen, ein Juwel zu machen, das 'rescue_from' außerhalb von Rails ermöglicht. https://github.com/shime/rescue_from_ruby – shime

Verwandte Themen