Rubyで例外を救出する
発生した例外をレスキューして、アプリケーションが呼び出しスタックの最上位に到達したときにアプリケーションがクラッシュするのを防ぐことができます。 Rubyでは、rescue
を使用します そのためのキーワード。
Rubyで例外をレスキューするときに、レスキューする必要のある特定のエラークラスを指定できます。
begin
raise 'This exception will be rescued!'
rescue StandardError => e
puts "Rescued: #{e.inspect}"
end
注 :raise
を使用する場合 例外クラスを指定しない場合、RubyはデフォルトでRuntimeError
になります 。
レスキューする単一の例外クラスを指定することに加えて、例外クラスの配列をrescue
に渡すことができます。 キーワード。これにより、同じ方法で複数のエラーに対応できるようになります。
begin
raise 'This exception will be rescued!'
rescue StandardError, AnotherError => e
puts "Rescued: #{e.inspect}"
end
複数のrescue
ブロックは、さまざまな方法でさまざまなエラーを処理するために使用できます。これは、さまざまなシナリオでさまざまな例外を生成するライブラリを操作する場合に役立ちます。
begin
raise 'This exception will be rescued!'
rescue StandardError => e
puts "Rescued: #{e.inspect}"
rescue AnotherError => e
puts "Rescued, but with a different block: #{e.inspect}"
end
例外階層
Rubyの例外階層は、さまざまなタイプのエラーを区別するために使用され、エラーのすべてを指定せずにエラーのグループから救済する機能を提供します。
ライブラリは独自の例外サブクラスを定義できますが、Ruby2.5に組み込まれている例外サブクラスのリストは次のようになります。
- NoMemoryError
- ScriptError
- LoadError
- NotImplementedError
- SyntaxError
- SecurityError
- SignalException
- Interrupt
- StandardError (default for `rescue`)
- ArgumentError
- UncaughtThrowError
- EncodingError
- FiberError
- IOError
- EOFError
- IndexError
- KeyError
- StopIteration
- LocalJumpError
- NameError
- NoMethodError
- RangeError
- FloatDomainError
- RegexpError
- RuntimeError (default for `raise`)
- SystemCallError
- Errno::*
- ThreadError
- TypeError
- ZeroDivisionError
- SystemExit
- SystemStackError
- fatal (impossible to rescue)
rescue
で例外クラスを省略する場合 ブロック、StandardError
が想定されます。 ArgumentError
およびNoMethodError
StandardError
のサブクラスです 、これらはブロック内で発生したときに救出されます。
例外階層がどのように機能するかの良い例は、SystemCallError
です。 、これは低レベルのプラットフォーム依存の例外クラスです。ファイルの読み取りまたは書き込み時に最もよく見られます。
RubyのFile.read
メソッドがファイルの読み取りに失敗した場合、メソッドは例外を発生させます。これは、ファイルが存在しない、プログラムがファイルを読み取るための適切な権限を持っていないなど、さまざまな理由で発生する可能性があります。
これらの問題はプラットフォームに依存するため、Rubyは、マシンで実行されているオペレーティングシステムの種類に応じてさまざまな例外を発生させる可能性があります。このような低レベルのエラーの場合、RubyはErrno::*
の別のリストを実装します -各プラットフォームの例外。
これらすべてのErrno::*
例外は、SystemCallError
のサブクラスです。 。これらはプラットフォーム固有ですが、rescue
で引き続き使用できます。 SystemCallError
から救出してブロックする 。
begin
File.read("does/not/exist")
rescue SystemCallError => e
puts "Rescued: #{e.inspect}"
end
嚥下の例外
通常、意図せずに例外を飲み込むのを防ぐために、例外を救済するときはできるだけ具体的にするのが最善です。
image = nil
begin
File.read(image.filename)
rescue
puts "File can't be read!"
end
この例では、image
変数はnil
です 、したがって、NoMethodError
が発生します #filename
を呼び出そうとしたとき その上(NoMethodError: undefined method `filename' for nil:NilClass
)。すべてのStandardError
サブクラスは(NoMethodError
を含む)から救出されます )、例外が飲み込まれ、「ファイルを読み取れません!」-メッセージが出力されます。これにより、コード内のバグの可能性が隠されます。
注 :可能ですが、Exception
を使用します rescue
のスーパークラス ブロックは強くお勧めしません。
Rubyで例外を発生または救済することについて質問がありますか? @AppSignalまでお気軽にお知らせください。もちろん、この記事がどのように気に入ったか、または別のテーマがある場合はもっと知りたいと思います。
-
Rubyで例外にコンテキストデータを追加する方法
標準のバックトレース/エラーメッセージの組み合わせでは不十分な場合があります。エラーの原因を特定するために、追加のデータが必要になる場合があります。幸い、Rubyで行うのはとても簡単です。 エラーメッセージのカスタマイズ エラーにコンテキスト情報を追加する最も簡単な方法は、それを例外のメッセージに追加することです。以下の例では、例外をキャッチし、新しいメッセージで再発生させています: begin raise foo rescue => e raise e.class, bar end # RuntimeError: bar このアプローチの良い使用例は、テンプレートをレン
-
TracePointを使用してRubyでの複雑な例外動作を調査する
特に大規模なアプリでは、例外を除いて何が起こっているのかを理解するのが非常に難しい場合があります。既存のプロジェクト内のコードで作業していると想像してください。例外を発生させると、何か奇妙なことが起こります。たぶん例外は飲み込まれます。たぶん、環境変数が変更されます。例外が別の例外にラップされる可能性があります。 TracePointsを使用して、例外が飲み込まれた場合でも、アプリの例外に関するもう少し情報を取得する簡単な方法を紹介します。 便利な例 Railsのコントローラーとビューの境界は、例外がロジックに反しているように見える1つの場所です。自分で見るのは簡単です。ビューで例外を発生