2013-05-15 18 views
6

Mam moduł, w którym wykonuję wszystkie moje zadania szyfrowania/odszyfrowywania dla projektu. Chciałbym uchwycić wszystkie wyjątki, które występują w tym module, aby móc sobie z nimi poradzić.Zapisywanie wszystkich błędów określonego typu wewnątrz modułu

Czy można zrobić coś takiego

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

wewnątrz modułu?

+1

czy włączasz ten moduł do kontrolera, czy nie? 'rescue_from' ma być używany tylko wewnątrz kontrolerów, więc robienie czegoś takiego w zwykłych starych obiektach z rubinem zawierałoby bardzo brudne hacki. – shime

+0

Ah, rozumiem. Dzięki @shime – Matt

+0

Chętnie pomogę. Sprawdź tutaj, jeśli chcesz wiedzieć, co mam na myśli przez brudne hacki: http://www.simonecarletti.com/blog/2009/12/inside-ruby-on-rails-rescuable-and-rescue_from/ - Nie podoba mi się jak rzeczy wyglądają, gdy robisz to w Ruby i wydaje się, że dodajesz niepotrzebny bałagan. Wyodrębnianie obsługi wyjątków we własnej metodzie jest sposobem na zwiększenie pewności kodu, który wydaje się pasować najbardziej do scenariusza. Przeczytaj więcej na ten temat tutaj: http://avdi.org/talks/confident-code-railsconf-2011/ – shime

Odpowiedz

7

Zbadałem trochę i przyniosłem rozwiązanie. Powiedziałeś, że masz moduł, w którym robisz szyfrowanie. Zgaduję, że ten moduł reprezentuje singleton. Moje rozwiązanie wymaga jednak zamiast tego instancji.

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

Wyodrębnić zachowanie szyfrowania w module.

module Encryptable 
    def encrypt 
     # ... 
    end 

    def decrypt 
     # ... 
    end 
end 

Utwórz nowy moduł obsługujący wyjątki.

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 

Więc teraz można użyć nowo zdefiniowane handle_known_exceptions wewnątrz Crypto. Nie jest to bardzo wygodne, ponieważ nie zyskałeś wiele. Trzeba jeszcze zadzwonić do obsługi wyjątku wewnątrz każdej metody:

class Crypto 
    include ExceptionHandler 

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

Nie trzeba tego robić, jeśli definiujemy Delegator że robi to za nas:

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 

Całkowicie nadpisać inicjalizacji Crypto, aby użyj zamiast tego delegata.

class Crypto 
    include Encryptable 

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

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

I to wszystko!

+1

Holy smokees, to naprawdę niesamowite - wielkie dzięki! Dam to! – Matt

+0

Haha, to przeszkadzało mi, ponieważ zadawałem sobie pytanie kilka razy. Zabawa z tym była dla mnie bardzo przyjemna, więc postanowiłem zrobić klejnot, który umożliwia 'rescue_from' poza Railsami. https://github.com/shime/rescue_from_ruby – shime

Powiązane problemy