Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

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までお気軽にお知らせください。もちろん、この記事がどのように気に入ったか、または別のテーマがある場合はもっと知りたいと思います。


  1. Rubyで例外にコンテキストデータを追加する方法

    標準のバックトレース/エラーメッセージの組み合わせでは不十分な場合があります。エラーの原因を特定するために、追加のデータが必要になる場合があります。幸い、Rubyで行うのはとても簡単です。 エラーメッセージのカスタマイズ エラーにコンテキスト情報を追加する最も簡単な方法は、それを例外のメッセージに追加することです。以下の例では、例外をキャッチし、新しいメッセージで再発生させています: begin raise foo rescue => e raise e.class, bar end # RuntimeError: bar このアプローチの良い使用例は、テンプレートをレン

  2. TracePointを使用してRubyでの複雑な例外動作を調査する

    特に大規模なアプリでは、例外を除いて何が起こっているのかを理解するのが非常に難しい場合があります。既存のプロジェクト内のコードで作業していると想像してください。例外を発生させると、何か奇妙なことが起こります。たぶん例外は飲み込まれます。たぶん、環境変数が変更されます。例外が別の例外にラップされる可能性があります。 TracePointsを使用して、例外が飲み込まれた場合でも、アプリの例外に関するもう少し情報を取得する簡単な方法を紹介します。 便利な例 Railsのコントローラーとビューの境界は、例外がロジックに反しているように見える1つの場所です。自分で見るのは簡単です。ビューで例外を発生