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:
-
FileNotFound
vsFileNotFoundError
-
DatabaseExploded
vsDatabaseExplodedError
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