Exception Handling

Ausnahmen werden in einem begin/end Block abgefangen

begin
  # code that might raise
rescue
  # handle exception
end

Wenn Sie sich innerhalb einer Methode befinden, müssen Sie begin oder end nicht verwenden, es sei denn, Sie möchten den Geltungsbereich abgefangener Ausnahmen einschränken

def my_method
  # ...
rescue
  # ...
end

Dasselbe gilt für eine class, module und block

[0, 1, 2].map do |i|
  10 / i
rescue ZeroDivisionError
  nil
end
#=> [nil, 10, 5]

Sie können die Ausnahme einer lokalen Variable zuweisen, indem Sie => variablen_name am Ende der rescue Zeile verwenden

begin
  # ...
rescue => exception
  warn exception.message
  raise # re-raise the current exception
end

Standardmäßig werden StandardError und seine Unterklassen abgefangen. Sie können einen bestimmten Satz von Ausnahmeklassen (und deren Unterklassen) abfangen, indem Sie sie nach rescue auflisten

begin
  # ...
rescue ArgumentError, NameError
  # handle ArgumentError or NameError
end

Sie können verschiedene Arten von Ausnahmen auf unterschiedliche Weise abfangen

begin
  # ...
rescue ArgumentError
  # handle ArgumentError
rescue NameError
  # handle NameError
rescue
  # handle any StandardError
end

Die Ausnahme wird von oben nach unten mit dem ersten passenden rescue Abschnitt abgeglichen und nur einmal. Wenn im begin Abschnitt ein ArgumentError ausgelöst wird, wird er nicht im StandardError Abschnitt behandelt.

Sie können abgefangene Ausnahmen erneut versuchen

begin
  # ...
rescue
  # do something that may change the result of the begin block
  retry
end

Die Ausführung wird am Anfang des begin Blocks fortgesetzt. Seien Sie also vorsichtig, um eine Endlosschleife zu vermeiden.

Innerhalb eines rescue Blocks ist die einzige gültige Stelle für retry, alle anderen Verwendungen lösen einen SyntaxError aus. Wenn Sie eine Blockiteration wiederholen möchten, verwenden Sie redo. Weitere Details finden Sie unter Kontrollausdrücke.

Um immer Code auszuführen, unabhängig davon, ob eine Ausnahme ausgelöst wurde oder nicht, verwenden Sie ensure

begin
  # ...
rescue
  # ...
ensure
  # this always runs BUT does not implicitly return the last evaluated statement.
end

Sie können auch Code ausführen, wenn keine Ausnahme ausgelöst wird

begin
  # ...
rescue
  # ...
else
  # this runs only when no exception was raised AND return the last evaluated statement
ensure
  # this always runs.
  # It is evaluated after the evaluation of either the `rescue` or the `else` block.
  # It will not return implicitly.
end

NB: Ohne explizites return im ensure Block gibt der begin/end Block die zuletzt ausgewertete Anweisung zurück, bevor in den ensure Block eingetreten wird.