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

レスキューブロック外でのRuby例外の処理

コードがその例外のライフサイクルを制御していない場合でも、最新の例外を取得できると便利なことがよくあります。アプリケーションに基本的なクラッシュ検出を追加したいとします。キャッチされなかった例外の結果として発生したクラッシュに関する追加情報をログに記録したい。

最初のステップは、アプリケーションが終了するたびに実行されるハンドラーを追加することです。 Rubyカーネルのat_exitメソッドを使用してこれを行うのは非常に簡単です。

at_exit
  puts "the app exited"
end

しかし、例外の結果として終了コールバックが呼び出されたかどうかをどのように知ることができますか?さて、Rubyは不可解な名前の$!を提供します グローバル変数。これには、現在のコールスタックのどこかで発生した最近発生した例外が含まれています。

$!を使用するのは簡単です 例外が原因でプログラムが終了しているかどうかを検出します。次のようになります:

at_exit do
 save_error_to_log($!) if $!         
end

$!の制限

残念ながら、$! メソッドは、現在の呼び出しスタックのどこかで例外が発生した場合にのみ機能します。例外を救済する場合は、$!にアクセスしてみてください レスキュー条項の外では、nilになります。

begin        
 raise "x"       
rescue       
 puts $! # => RuntimeError           
end

puts $! # => nil         

これは、$!を意味します IRBのようなシェルの内部ではかなり役に立たない。多くの場合、IRBでは、メソッドを実行して例外を取得します。その例外オブジェクトを入手したい場合があります。しかし、$! これでは機能しません。

irb(main):001:0> 1/0
ZeroDivisionError: divided by 0
    from (irb):1:in `/'
irb(main):002:0> $!
=> nil

$を回避する! PRY付き

PRYは$!の制限を回避します 独自のローカル変数_ex_を追加する 。この変数には、キャッチされていない最新の例外が含まれています。

[1] pry(main)> raise "hi"        
RuntimeError: hi         
from (pry):1:in `__pry__'        
[2] pry(main)> _ex_      
=> #<RuntimeError: hi>

PRYがこれを実行できる理由は、PRYまたはIRB内にキャッチされない例外が実際にはないためです。シェル自体が例外をキャッチし、適切にフォーマットされたエラーメッセージとして表示します。

以下のPRYソースの関連ビットをコピーしました。コマンドを評価するコードがbegin/rescue/endブロック内にラップされていることがわかります。レスキュー可能な例外が発生すると、PRYは例外をself.last_exceptionに保存し、後で_ex_に割り当てられます。 。

# Excerpted from the PRY source at https://github.com/pry/pry/blob/623306966bfa86890ac182bc8375ec9699abe90d/lib/pry/pry_instance.rb#L273

begin
  if !process_command_safely(line)
    @eval_string << "#{line.chomp}\n" if !line.empty? || !@eval_string.empty?
  end
rescue RescuableException => e
  self.last_exception = e
  result = e

  Pry.critical_section do
    show_result(result)
  end
  return
end
英語が必要

おそらく、$!のような変数名を見つけるでしょう。 目に少し難しい?幸い、Rubyには「English」と呼ばれるモジュールが含まれています。このモジュールは、他の方法ではロボットのcusswordsのように見える多くのグローバル変数の英語バージョンを提供します。

$!の同義語 $ERROR_INFOです 。通常$!を使用する場所ならどこでも使用できます 。

require "English"

begin        
 raise "x"       
rescue       
 puts $ERROR_INFO # => RuntimeError          
end

そして、他の英語の同等物のほとんどは、このブログ投稿のトピックとは何の関係もありませんが、私はそれらをキックに含めています。英語の変数は左側にあります。オリジナルは右側にあります。

$ ERROR_INFO $!
$ ERROR_POSITION $ @
$ FS $;
$ FIELD_SEPARATOR $;
$ OFS $、
$ OUTPUT_FIELD_SEPARATOR $、
$ RS $ /
$ INPUT_RECORD_SEPARATOR $ /
$ ORS $ \
$ OUTPUT_RECORD_SEPARATOR $ \
$ INPUT_LINE_NUMBER $。
$ NR $。
$ LAST_READ_LINE $ _
$ DEFAULT_OUTPUT $>
$ DEFAULT_INPUT $ <
$ PID $$
$ PROCESS_ID $$
$ CHILD_STATUS $?
$ LAST_MATCH_INFO $〜
$ IGNORECASE $ =
$ ARGV $ *
$ MATCH $&
$ PREMATCH $ `
$ POSTMATCH $‘
$ LAST_PAREN_MATCH $ +


  1. Ruby Mapメソッドの使用方法(例付き)

    Mapは、配列、ハッシュ、範囲で使用できるRubyメソッドです。 マップの主な用途は、データを変換することです。 例 : 文字列の配列が与えられた場合、すべての文字列に目を通し、すべての文字を大文字にすることができます。 または、Userのリストがある場合 オブジェクト… 変換できます 対応するメールアドレス、電話番号、またはその他の属性のリストにそれらを追加します Userで定義 クラス。 これを行う方法を正確に見てみましょう! ルビーマップ構文 マップの構文は次のようになります: array = [a, b, c] array.map { |string| string.

  2. RubyでN-Queensの問題を解決する

    N-Queensは、 N*NボードにN個のクイーンを配置する必要がある興味深いコーディングチャレンジです。 。 次のようになります: 女王はすべての方向に移動できます: 垂直 水平 対角線 解決策(多くの場合があります)は、すべてのクイーンをボードに配置する必要があります。 &すべての女王は他のすべての女王の手の届かないところにいる必要があります。 この記事では、私がどのようにして解決策を思いついたのかを学びます。 計画 この種の課題を解決するときは、まず、計画を平易な英語で書き留めることから始めるのがよいでしょう。 これは、問題が何であるか、およびそれを解決するための手