Exception 處理

例外在 begin/end 區塊中被救援

begin
  # code that might raise
rescue
  # handle exception
end

如果您在方法中,則不需要使用 beginend,除非您希望限制被救援例外的範圍

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

對於 classmoduleblock 也是如此

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

您可以透過在 rescue 行尾使用 => variable_name 將例外指派給局部變數

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

預設情況下,StandardError 及其子類別會被救援。您可以透過在 rescue 之後列出特定集合的例外類別(及其子類別)來救援它們

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

您可以用不同的方式救援不同類型的例外

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

例外會與從頂端開始的救援區段相符,且只會相符一次。如果在 begin 區段中引發 ArgumentError,它將不會在 StandardError 區段中被處理。

您可以重試被救援的例外

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

執行會從 begin 區塊的開頭繼續,因此請小心不要建立無限迴圈。

在救援區塊內是 retry 唯一有效的放置位置,所有其他用途都會引發 SyntaxError。如果您想重試區塊迭代,請使用 redo。有關詳細資訊,請參閱 控制表達式

若要無論是否引發例外狀況,都要執行某些程式碼,請使用 ensure

begin
  # ...
rescue
  # ...
ensure
  # this always runs
end

您也可以在未引發例外狀況時執行某些程式碼

begin
  # ...
rescue
  # ...
else
  # this runs only when no exception was raised
ensure
  # ...
end