English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Ruby 異常

異常と実行は常に関連付けられています。存在しないファイルを開いた場合、それを適切に処理しないと、プログラムは低品質と見なされます。

異常が発生すると、プログラムが停止します。異常は、プログラムの実行中に発生する可能性のあるさまざまなタイプのエラーを処理するために使用されます。したがって、プログラムが完全に停止しないように適切な行動を取る必要があります。

Ruby は、異常を処理するための完璧なメカニズムを提供しています。私たちは、 begin/end ブロックに異常を投げる可能性のあるコードを追加し、 rescue 子句が Ruby が処理するべき異常の種類を指示します。

文法

begin # 開始
 
 raise.. # 異常を投げる
 
rescue [ExceptionType = StandardException] # 指定されたタイプの例外をキャッチするデフォルトは StandardException
 $! # 異常情報を示す
 $@ # 異常が発生したコード位置を示す
else # その他の例外
 ..
ensure # 例外がなくても、このコードブロックに入ります
 
end # 終了

から beginrescue の中のすべては保護されています。コードブロックの実行中に例外が発生すると、制御は rescueend の間のブロック。

に対して begin ブロックの各 rescue 節、Rubyは投げられた例外を各パラメータと交互に比較します。rescue節で名前付けられた例外が現在投げられた例外のタイプと一致したり、その親クラスである場合、マッチングが成功します。

もし例外が指定されたすべてのエラータイプに一致しない場合、すべての rescue 節の後で、 else 節。

オンラインサンプル

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
      file = STDIN
end
print file, "==", STDIN, "\n"

上記のサンプルの実行結果は以下の通りです。あなたは、STDINfile 、なぜならオープン失敗しました。

#<IO:0xb7d16f84>==#<IO:0xb7d16f84>

を使用して retry

あなたは rescue ブロックが例外をキャッチし、以下を使用して retry 文は先頭から開始します begin ブロック。

文法

begin
    # このブロックから投げ出された例外は以下のrescue節でキャッチされます
rescue
    # このブロックはすべての種類の例外をキャッチします
    retry # コントロールをbeginの先頭に戻します
end

オンラインサンプル

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
   fname = "existant_file"
   retry
end

以下は処理プロセスです:

  • オープン中に例外が発生しました。

  • rescueにジャンプします。fnameが再割り当てされます。

  • retryを使ってbeginの先頭にジャンプします。

  • この回ではファイルが成功して開かれました。

  • 基本のプロセスを続けます。

注意:このサンプルコードでは、リネームされたファイルが存在しない場合、無限に試みます。したがって、例外処理では慎重に使用してください。 retryを使用できます。

を使用して raise

あなたは raise この文は例外を投げ出し、以下のメソッドが呼び出されるときに例外を投げ出します。その2番目のメッセージが表示されます。

文法

raise 
 
または
 
raise "Error Message" 
 
または
 
raise ExceptionType, "Error Message"
 
または
 
raise ExceptionType, "Error Message" condition

第1種形式は単に現在の例外を再投げ(現在の例外がなければ RuntimeError を投げ)します。これは、例外を説明する前に例外を処理する必要がある場合に使用されます。

第2種形式で新しい RuntimeError 例外を設定し、そのメッセージを指定された文字列にします。その例外はその後、呼び出しスタックに投げられます。

第3種形式は、最初の引数を使って例外を作成し、関連するメッセージを第2引数で設定します。

第四の形式は第三の形式に似ており、追加の条件文(例えば}} unless)を使用して例外を投げます。

オンラインサンプル

#!/usr/bin/ruby
 
begin  
    puts 'I am before the raise.'  
    raise 'An error has occurred.'  
    puts 'I am after the raise.'  
rescue  
    puts 'I am rescued.'  
end  
puts 'I am after the begin block.'

以下の例の実行結果は:

I am before the raise.  
I am rescued.  
I am after the begin block.

別のデモ raise 使用例:

オンラインサンプル

#!/usr/bin/ruby
 
begin  
  raise 'A test exception.'  
rescue Exception => e  
  puts e.message  
  puts e.backtrace.inspect  
end

以下の例の実行結果は:

A test exception.
["main.rb:4"]

を使用して ensure

時には、例外が投げられるかどうかにかかわらず、コードブロックの終了時に処理を行う必要があることがあります。例えば、ファイルを開いた場合、ブロックから退出する際にファイルを閉じることを確保する必要があるかもしれません。

ensure 子句はこれをします。ensureは最後のrescue子句の後に配置され、ブロックが終了時に常に実行されるコードブロックを含みます。これにより、ブロックが正常に終了したか、例外を投げて処理したか、未捕獲の例外により終了したかに関わらず、ensure ブロックは常に実行されます。

文法

begin 
   #.. プロセス
   #.. 例外を投げます
rescue 
   #.. エラーを処理します 
ensure 
   #.. 最後に実行を確保します
   #.. これは常に実行されます
end

オンラインサンプル

begin
  raise 'A test exception.'
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
ensure
  puts \
end

以下の例の実行結果は:

A test exception.
["main.rb:4"]
実行を確保

を使用して else

提供された場合 else 子句は、一般的に以下に配置されます rescue 子句の後、任意 ensure 以前。

else 子句の主体は、コードの主体が例外を投げない場合にのみ実行されます。

文法

begin 
   #.. プロセス 
   #.. 例外を投げます
rescue 
   #.. エラーを処理します
else
   #.. エラーがなければ実行します
ensure 
   #.. 最後に実行を確保します
   #.. これは常に実行されます
end

オンラインサンプル

begin
 # 'A test exception.' を投げます
 puts \
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
else
   puts \-- エラーはありません!"
ensure
  puts \
end

以下の例の実行結果は:

例外を発生させません
おめでとうございます-- エラーはありません!
実行を確保

throw されたエラーメッセージをキャプチャするために $! 変数を使用できます。

Catch と Throw

raise と rescue の例外メカニズムは、エラーが発生したときに実行を中断し、時には通常の処理中に深層のネストされた構造から抜け出す必要がある場合があります。その場合、catch と throw が役立ちます。

catch 指定された名前(SymbolまたはStringができます)を使用してタグを定義する。ブロックは throw に達するまで通常通りに実行されます。

文法

throw :lablename
#.. これは実行されません
catch :lablename do
#.. throw が見つかった場合に実行される catch とマッチング
end
 
または
 
throw :lablename condition
#.. これは実行されません
catch :lablename do
#.. throw が見つかった場合に実行される catch とマッチング
end

オンラインサンプル

以下の例では、ユーザーがどのプレースホルダーにも '!' を入力すると、throwを使ってユーザーとのインタラクションを終了します。

オンラインサンプル

def promptAndGet(prompt)
   print prompt
   res = readline.chomp
   res == "!" then throw :quitRequested
   return res
end
 
catch :quitRequested do
   name = promptAndGet("Name:  ")
   age = promptAndGet("Age:  ")
   sex = promptAndGet("Sex:  ")
   # ..
   # 情報処理
end
promptAndGet("Name:")

上記のプログラムは手動でのインタラクションが必要であり、あなたのコンピュータで試してみることができます。以下の例の実行結果は以下の通りです:

Name: Ruby on Rails
Age: 3
Sex: !
Name:Just Ruby

クラス Exception

Rubyの標準クラスとモジュールは例外を投げます。すべての例外クラスは、顶点の Exception クラスを含む階層を形成します。次のレベルには、7種類の異なるタイプがあります:

  • Interrupt

  • NoMemoryError

  • SignalException

  • ScriptError

  • StandardError

  • SystemExit

Fatal はこのレベルの別の例外ですが、Ruby インタプリタは内部でのみそれを使用します。

ScriptError と StandardError にはいくつかのサブクラスがありますが、ここではその詳細を知る必要はありません。最も重要なことは、自分自身の例外クラスを作成することで、それらはクラス Exception またはそのサブクラスのサブクラスでなければなりません。

以下の例を見てみましょう:

オンラインサンプル

class FileSaveError < StandardError
   attr_reader :reason
   def initialize(reason)
      @reason = reason
   end
end

以下の例を見て、上記の例外を使用します:

オンラインサンプル

File.open(path, "w") do |file|
begin
    # データを出力する...
rescue
    # エラー発生
    raise FileSaveError.new($!)
end
end

ここでは、最も重要な行は raise です。 FileSaveError.new($!)。我々は raise を使って例外が発生したことを示し、それを FileSaveError の新しい例に渡します。特定の例外によりデータの書き込みが失敗しました。