Ruby Language
Ausnahmen
Suche…
Bemerkungen
Eine Ausnahme ist ein Objekt, das das Auftreten einer Ausnahmebedingung darstellt. Mit anderen Worten, es zeigt an, dass etwas schief gelaufen ist.
In Ruby werden Ausnahmen oft als Fehler bezeichnet . Dies liegt daran, dass die Basis- Exception Klasse als Exception -Objektelement der obersten Ebene vorhanden ist, aber benutzerdefinierte Ausführungsausnahmen sind im Allgemeinen StandardError oder Nachkommen.
Ausnahme auslösen
Um eine Exception Kernel#raise verwenden Sie Kernel#raise übergeben Sie die Exception-Klasse und / oder die Nachricht:
raise StandardError # raises a StandardError.new
raise StandardError, "An error" # raises a StandardError.new("An error")
Sie können auch einfach eine Fehlermeldung übergeben. In diesem Fall wird die Nachricht in einen RuntimeError :
raise "An error" # raises a RuntimeError.new("An error")
Hier ist ein Beispiel:
def hello(subject)
raise ArgumentError, "`subject` is missing" if subject.to_s.empty?
puts "Hello #{subject}"
end
hello # => ArgumentError: `subject` is missing
hello("Simone") # => "Hello Simone"
Erstellen eines benutzerdefinierten Ausnahmetyps
Eine benutzerdefinierte Ausnahme ist jede Klasse, die Exception oder eine Unterklasse von Exception .
Im Allgemeinen sollten Sie StandardError oder einen Nachkommen immer erweitern. Die Exception bezieht sich normalerweise auf Fehler der virtuellen Maschine oder des Systems. Wenn Sie sie retten, kann eine erzwungene Unterbrechung nicht wie erwartet funktionieren.
# Defines a new custom exception called FileNotFound
class FileNotFound < StandardError
end
def read_file(path)
File.exist?(path) || raise(FileNotFound, "File #{path} not found")
File.read(path)
end
read_file("missing.txt") #=> raises FileNotFound.new("File `missing.txt` not found")
read_file("valid.txt") #=> reads and returns the content of the file
Es ist üblich, Ausnahmen zu benennen, indem am Ende das Suffix " Error hinzugefügt wird:
-
ConnectionError -
DontPanicError
Wenn jedoch der Fehler selbsterklärend ist, brauchen Sie nicht den hinzufügen Error Suffix da wäre überflüssig:
-
FileNotFoundvsFileNotFoundError -
DatabaseExplodedvsDatabaseExplodedError
Behandlung einer Ausnahme
Verwenden Sie den begin/rescue , um eine Ausnahme abzufangen (Rettung), und behandeln Sie sie:
begin
# an execution that may fail
rescue
# something to execute in case of failure
end
Eine rescue ist analog zu einem catch Block in einer geschweiften Klammer wie C # oder Java.
Eine bloße rescue wie diese rettet StandardError .
Anmerkung: Achten Sie darauf, dass Sie anstelle des Standard- StandardError keine Exception fangen. Die Exception Klasse enthält SystemExit und NoMemoryError sowie andere schwerwiegende Ausnahmen, die Sie normalerweise nicht abfangen möchten. Erwägen Sie stattdessen immer StandardError (die Standardeinstellung).
Sie können auch die Ausnahmeklasse angeben, die gerettet werden soll:
begin
# an excecution that may fail
rescue CustomError
# something to execute in case of CustomError
# or descendant
end
Diese Rettungsklausel fängt keine Ausnahme ab, die kein CustomError .
Sie können die Ausnahme auch in einer bestimmten Variablen speichern:
begin
# an excecution that may fail
rescue CustomError => error
# error contains the exception
puts error.message # provide human-readable details about what went wrong.
puts error.backtrace.inspect # return an array of strings that represent the call stack
end
Wenn Sie eine Ausnahme nicht behandelt haben, können Sie sie jederzeit in einem Rettungsblock auslösen.
begin
#here goes your code
rescue => e
#failed to handle
raise e
end
Wenn Sie Ihr wiederholen möchten begin Block, rufen retry :
begin
#here goes your code
rescue StandardError => e
#for some reason you want to retry you code
retry
end
Sie können in einer Schleife stecken bleiben, wenn Sie bei jeder Wiederholung eine Ausnahme feststellen. Um dies zu vermeiden, beschränken Sie Ihr retry_count auf eine bestimmte Anzahl von Versuchen.
retry_count = 0
begin
# an excecution that may fail
rescue
if retry_count < 5
retry_count = retry_count + 1
retry
else
#retry limit exceeds, do something else
end
Sie können auch einen else Block oder einen ensure bereitstellen. Ein else Block wird ausgeführt, wenn der begin Block ohne Auslösung einer Ausnahme abgeschlossen ist. Ein ensure wird immer ausgeführt. Ein ensure ist analog zu einem finally Block in einer geschweiften Klammer wie C # oder Java.
begin
# an execution that may fail
rescue
# something to execute in case of failure
else
# something to execute in case of success
ensure
# something to always execute
end
Wenn Sie sich in einem def , module oder class Block befinden, müssen Sie die begin-Anweisung nicht verwenden.
def foo
...
rescue
...
end
Behandlung mehrerer Ausnahmen
Sie können mehrere Fehler in derselben rescue :
begin
# an execution that may fail
rescue FirstError, SecondError => e
# do something if a FirstError or SecondError occurs
end
Sie können auch mehrere rescue hinzufügen:
begin
# an execution that may fail
rescue FirstError => e
# do something if a FirstError occurs
rescue SecondError => e
# do something if a SecondError occurs
rescue => e
# do something if a StandardError occurs
end
Die Reihenfolge der rescue ist relevant: Die erste Übereinstimmung ist die ausgeführte. Wenn Sie also StandardError als erste Bedingung setzen und alle Ihre Ausnahmen von StandardError erben, werden die anderen rescue niemals ausgeführt.
begin
# an execution that may fail
rescue => e
# this will swallow all the errors
rescue FirstError => e
# do something if a FirstError occurs
rescue SecondError => e
# do something if a SecondError occurs
end
Einige Blöcke haben implizite Ausnahmebehandlung wie def , class und module . Mit diesen Blöcken können Sie die begin Anweisung überspringen.
def foo
...
rescue CustomError
...
ensure
...
end
Hinzufügen von Informationen zu (benutzerdefinierten) Ausnahmen
Es kann hilfreich sein, zusätzliche Informationen mit einer Ausnahme hinzuzufügen, z. B. zu Protokollierungszwecken oder zur bedingten Behandlung, wenn die Ausnahme abgefangen wird:
class CustomError < StandardError
attr_reader :safe_to_retry
def initialize(safe_to_retry = false, message = 'Something went wrong')
@safe_to_retry = safe_to_retry
super(message)
end
end
Ausnahme auslösen:
raise CustomError.new(true)
Die Ausnahme abfangen und auf die zusätzlichen Informationen zugreifen:
begin
# do stuff
rescue CustomError => e
retry if e.safe_to_retry
end