サーチ…


備考

例外は、例外条件の発生を表すオブジェクトです。つまり、何かが間違っていたことを示しています。

Rubyでは、 例外はしばしばエラーと呼ばれます。これは、基本Exceptionクラスがトップレベルの例外オブジェクト要素として存在するためですが、ユーザー定義の実行例外は一般にStandardErrorまたは子孫です。

例外を発生させる

例外を発生させるには、 Kernel#raiseが例外クラスおよび/またはメッセージを渡します:

raise StandardError # raises a StandardError.new
raise StandardError, "An error" # raises a StandardError.new("An error")

単にエラーメッセージを渡すこともできます。この場合、メッセージはRuntimeErrorラップされます。

raise "An error" # raises a RuntimeError.new("An error")

ここに例があります:

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"

カスタム例外タイプの作成

カスタム例外を拡張するすべてのクラスであるExceptionまたはサブクラスのException

通常、 StandardErrorまたはその子孫を拡張する必要があります。 Exceptionファミリは通常、仮想マシンエラーまたはシステムエラーのために救済され、強制的な中断が予想通りに機能しないようにすることができます。

# 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

最後にErrorサフィックスを追加することで、例外に名前を付けるのが一般的です。

  • ConnectionError
  • DontPanicError

ただし、エラーが自明である場合、冗長であるため、 Errorサフィックスを追加する必要はありません。

  • FileNotFoundFileNotFoundError
  • DatabaseExplodedDatabaseExplodedError

例外の処理

begin/rescueブロックを使用して例外を捕捉(レスキュー)し、それを処理します。

begin
  # an execution that may fail
rescue
  # something to execute in case of failure
end

rescue句は、C#やJavaなどの中括弧で囲まれたcatchブロックに似ています。

このような裸のrescueStandardError救う。

注意:デフォルトのStandardError代わりにExceptionをキャッチしないよう注意してください。 ExceptionクラスにはSystemExitNoMemoryError含まれ、通常はキャッチしたくない重大な例外があります。代わりに、常にStandardError (デフォルト)をキャッチすることを検討してください。

レスキューする必要がある例外クラスを指定することもできます。

begin
  # an excecution that may fail
rescue CustomError
  # something to execute in case of CustomError
  # or descendant
end

このレスキュー句は、 CustomErrorではない例外をキャッチしません。

特定の変数に例外を格納することもできます。

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

例外処理に失敗した場合は、レスキューブロックでいつでも例外を発生させることができます。

begin
   #here goes your code
rescue => e
    #failed to handle 
    raise e
end

あなたが再試行したい場合はbeginブロックを、呼び出しretry

begin
   #here goes your code
rescue StandardError => e
   #for some reason you want to retry you code
   retry
end

再試行ごとに例外を検出すると、ループに陥る可能性があります。これを避けるには、 retry_countを特定の試行回数に制限します。

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

elseブロックまたはensureブロックを指定することもできます。 elseブロックは、例外がスローされずにbeginブロックが完了したときに実行されます。 ensureブロックは常に実行されます。 ensureブロックは、C#やJavaのような中括弧のfinallyブロックに似ています。

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

defmoduleまたはclassブロックの内部にある場合は、begin文を使用する必要はありません。

def foo
    ...
rescue
    ...
end

複数の例外の処理

同じrescue宣言で複数のエラーを処理することができます:

begin
  # an execution that may fail
rescue FirstError, SecondError => e
  # do something if a FirstError or SecondError occurs
end

複数のrescue宣言を追加することもできます。

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

rescueブロックの順序は関係します。最初の一致は実行されたものです。したがって、 StandardErrorを最初の条件として置き、すべての例外がStandardErrorから継承する場合、他のrescueステートメントは決して実行されません。

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

いくつかのブロックはdefclassmoduleような暗黙の例外処理を持っていmodule 。これらのブロックを使用すると、 begin文をスキップできます。

def foo
    ...
rescue CustomError
    ...
ensure
    ...
end

(カスタム)例外への情報の追加

例えば、ロギング目的で、または例外がキャッチされたときに条件付き処理を許可するために、例外とともに追加情報を含めると便利です。

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

例外を発生させる:

raise CustomError.new(true)

例外をキャッチし、提供された追加情報にアクセスする:

begin
  # do stuff
rescue CustomError => e
  retry if e.safe_to_retry
end


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow