Menu
Coddy logo textTech

ensure と raise

CoddyのRubyジャーニー「ロジックとフロー」セクションの一部 — レッスン 46/56。

さらに2つの要素がエラーハンドリングのツールキットを完成させます。

ensure は、begin が正常に終了したか、rescue 節が例外をキャッチしたか、あるいは例外がキャッチされなかった場合でも、何があっても実行されるブロックです。ここはクリーンアップコードを記述する場所です:

begin
  puts "opening file"
  raise "something broke"
rescue
  puts "caught it"
ensure
  puts "closing file"
end
# ファイルを開いています
# キャッチしました
# ファイルを閉じています

raise は、独自の例外を作成する方法です。メッセージとして文字列を渡すか、クラスとメッセージを渡します:

def withdraw(amount)
  raise ArgumentError, "amount must be positive" if amount <= 0
  # ... 引き出し処理を行う
end

慣習では、引数が誤っている場合に早期に失敗(fail fast)させるため、メソッドの先頭で早期に raise します。呼び出し側は、適切な回復処理がある場合には rescue するか、あるいはそのまま上位に伝播させることができます。

challenge icon

チャレンジ

簡単

以下の処理を行うメソッド safe_divide(a, b) を定義してください:

  • b == 0 の場合、メッセージ "b cannot be zero" を持つ ArgumentError を発生させる
  • それ以外の場合は a / b を返す

次に、入力から2つの整数を読み取ります。begin / rescue / ensure の中で safe_divide を呼び出してください:

  • 成功した場合は、Result: <value> を出力する
  • ArgumentError が発生した場合は、Error: <message> を出力する
  • ensure 内では、常に Done. を出力する

入力が 10 / 2 の場合、出力は以下のようになります:

Result: 5
Done.

入力が 10 / 0 の場合:

Error: b cannot be zero
Done.

チートシート

ensure は何があっても(正常終了、レスキューされた場合、または捕捉されなかった例外が発生した場合でも)実行されます。クリーンアップに使用します:

begin
  raise "something broke"
rescue
  puts "caught it"
ensure
  puts "always runs"
end

raise は例外を発生させます。特定の型を発生させるには、クラスとメッセージを渡します:

raise ArgumentError, "amount must be positive" if amount <= 0

慣習:不正な引数に対して早期に失敗(fail fast)させるため、メソッドの先頭で早期に raise します。

自分で試してみよう

# TODO: safe_divide(a, b) を定義する。b == 0 のときに ArgumentError を発生させる

a = gets.to_i
b = gets.to_i

# TODO: begin ... Result を print する; rescue ArgumentError => e ... Error を print する; ensure ... Done を print する
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

ロジックとフローのすべてのレッスン