Ruby Language
例外
サーチ…
備考
例外は、例外条件の発生を表すオブジェクトです。つまり、何かが間違っていたことを示しています。
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
サフィックスを追加する必要はありません。
-
FileNotFound
とFileNotFoundError
-
DatabaseExploded
とDatabaseExplodedError
例外の処理
begin/rescue
ブロックを使用して例外を捕捉(レスキュー)し、それを処理します。
begin
# an execution that may fail
rescue
# something to execute in case of failure
end
rescue
句は、C#やJavaなどの中括弧で囲まれたcatch
ブロックに似ています。
このような裸のrescue
はStandardError
救う。
注意:デフォルトのStandardError
代わりにException
をキャッチしないよう注意してください。 Exception
クラスにはSystemExit
とNoMemoryError
含まれ、通常はキャッチしたくない重大な例外があります。代わりに、常に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
def
、 module
または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
いくつかのブロックはdef
、 class
、 module
ような暗黙の例外処理を持ってい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