Nie mogę znaleźć wielu informacji o niestandardowych klasach wyjątków.
Co ja wiem
Możesz zadeklarować swoją niestandardową klasę błędu i pozwolić jej dziedziczyć z StandardError
, więc może być rescue
d:
class MyCustomError < StandardError
end
Pozwala to podnieść go za pomocą:
raise MyCustomError, "A message"
a później otrzymaj tę wiadomość podczas ratowania
rescue MyCustomError => e
puts e.message # => "A message"
Czego nie wiem
Chcę dać mojemu wyjątkowi niektóre pola niestandardowe, ale chcę odziedziczyć message
atrybut z klasy nadrzędnej. Dowiedziałem się, czytając na ten temat, że @message
nie jest zmienną instancji klasy wyjątku, więc martwię się, że moje dziedziczenie nie zadziała.
Czy ktoś może podać mi więcej szczegółów na ten temat? Jak zaimplementować niestandardową klasę błędu z object
atrybutem? Czy poniższe informacje są poprawne:
class MyCustomError < StandardError
attr_reader :object
def initialize(message, object)
super(message)
@object = object
end
end
I wtedy:
raise MyCustomError.new(anObject), "A message"
dostać:
rescue MyCustomError => e
puts e.message # => "A message"
puts e.object # => anObject
czy to zadziała, a jeśli tak, to czy jest to właściwy sposób postępowania?
rescue Exception => e
. Jest szerszy niż domyślny,rescue => e
który rozciąga się odStandardError
i przechwytuje wszystko, w tym Ctrl + C. Zrobiłbymrescue MyCustomError => e
.Odpowiedzi:
raise
ustawia już wiadomość, więc nie musisz jej przekazywać do konstruktora:Mam wymienić
rescue Exception
zrescue MyCustomError
zobacz Dlaczego jest to zły styl `Exception ratunkowej => e` w Ruby? .źródło
rescue Exception
, ale dlaczego nierescue MyCustomError
?raise MyCustomError, "a message"
bez niejnew
, „komunikat” nie zostanie ustawiony.Biorąc pod uwagę, o czym mówi dokumentacja Ruby Core
Exception
, z której dziedziczą wszystkie inne błędy#message
http://ruby-doc.org/core-1.9.3/Exception.html#method-i-message
Wybrałbym redefinicję
to_s
/to_str
lub inicjalizator. Oto przykład, w którym chcemy wiedzieć, w sposób w większości czytelny dla człowieka, kiedy usługa zewnętrzna czegoś nie zrobiła.UWAGA: Druga strategia poniżej wykorzystuje ładne metody łańcuchowe rails, takie jak
demodualize
, które mogą być nieco skomplikowane, a zatem potencjalnie nierozsądne w przypadku wyjątków. W razie potrzeby możesz również dodać więcej argumentów do podpisu metody.Zastępowanie strategii #to_s, a nie #to_str, działa inaczej
Wyjście konsoli
Zastępowanie #initialize Strategy
To strategia najbliższa implementacjom, których używałem w railsach. Jak wspomniano powyżej, używa się
demodualize
,underscore
ihumanize
ActiveSupport
metod. Ale można to łatwo usunąć, tak jak w poprzedniej strategii.Wyjście konsoli
Narzędzie demonstracyjne
To jest demo pokazujące ratowanie i wysyłanie wiadomości z powyższej implementacji. Klasa podnosząca wyjątki to fałszywe API do Cloudinary. Po prostu wrzuć jedną z powyższych strategii do konsoli rails, a następnie wykonaj tę.
źródło
Twój pomysł jest słuszny, ale sposób, w jaki go nazywasz, jest zły. Powinno być
źródło
raise
słowa kluczowego czy coś w tym stylu.initialize
aby przyjąć dwa argumenty.new
przekazuje argumenty doinitialize
.raise(BillRowError.new(:roamingcalls, @index), "Roaming Calls field missing")
. Dlatego wywołujeraise
z dwoma parametrami: nowyBillRowError
obiekt i jego wiadomość. Jestem po prostu zdezorientowany składnią ... W innych tutorialach zawsze widzę to tak:raise Error, message
raise
; to jest dość elastyczne. Problem polega na tym, że zdefiniowałeśinitialize
dwa argumenty i podałeś tylko jeden. Spójrz na swój przykład.BillRowError.new(:roamingcalls, @index)
otrzymuje dwa argumenty.Chciałem zrobić coś podobnego. Chciałem przekazać obiekt do #new i ustawić komunikat w oparciu o przetwarzanie przekazanego obiektu. Następujące prace.
Zauważ, że jeśli nie zadeklarujesz,
attr_accessor :message
to nie zadziała. Rozwiązując problem OP, możesz również przekazać wiadomość jako dodatkowy argument i zapisać wszystko, co chcesz. Wydaje się, że kluczową częścią jest nadpisanie #message.źródło