Rubyの例外処理とは?begin・rescue・ensureの使い方を解説

PR Ruby

Rubyの例外処理とは?begin・rescue・ensureの使い方を解説

💡 この記事でわかること

  • 例外(エラー)とは何か、なぜプログラムが止まるのか
  • beginrescue でエラーをキャッチして処理を続ける方法
  • エラーの種類を指定してキャッチする方法と、rescue => e でのメッセージ取得
  • elseensure の役割、raise でわざと例外を出す方法
  • メソッド定義では begin を省略できること、初心者がよく出会うエラー一覧

1. 例外(エラー)とは?

例外とは、
👉 プログラムの実行中に発生する「想定外の事態」のことです。エラーと呼ばれることも多いです。

たとえば、次のコードは「数字」を期待していますが、利用者が abc と入力すると例外が発生します。

print "数字を入力: "
num = Integer(gets.chomp)
puts num * 2

# 「abc」と入力すると…
# `Integer': invalid value for Integer(): "abc" (ArgumentError)

👉 例外が発生すると、そこでプログラムは強制的に停止し、それ以降の処理は実行されません。この「停止」を防ぎ、エラーが起きても処理を続けられるようにするのが例外処理です。

💡 gets.chomp.to_i はエラーにならず 0 を返しますが、Integer() は変換できないと例外を出します。「不正な入力をはっきりエラーにしたい」ときは Integer() を使い、例外処理と組み合わせます。

👉 Rubyのデータ型(型変換・to_iとの違い)についての記事はこちら


2. begin・rescue の基本

begin のブロックに「エラーが起きるかもしれない処理」、rescue のブロックに「エラーが起きたときの処理」を書き、end で閉じます。

begin
  print "数字を入力: "
  num = Integer(gets.chomp)
  puts "2倍すると #{num * 2} です"
rescue ArgumentError
  puts "数字を入力してください"
end

puts "プログラムは続行します"
  • begin の中でエラーが起きなければ、rescueスキップされる
  • エラーが起きると、その時点で rescue に移る(begin の残りは実行されない)
  • rescue で処理したあとは、プログラムは止まらずに先に進む

3. エラーの種類を指定する

rescue ZeroDivisionError のように書くと、その種類のエラーだけをキャッチします。想定していない別のエラーはそのまま止まってくれるので、原因に気づけます。

begin
  result = 10 / 0
rescue ZeroDivisionError
  puts "0で割ることはできません"
end

💡 種類を書かずに rescue だけにすると、StandardError という「よくあるエラーのグループ」をまとめてキャッチしますrescue Exception と書くと、Ctrl + C による中断など、本来止めるべきものまで拾ってしまうため、初心者のうちは rescue(種類なし)か rescue StandardError にとどめてください。

複数の種類を分けて処理する

begin
  a = Integer(gets.chomp)
  b = Integer(gets.chomp)
  puts a / b
rescue ArgumentError
  puts "数字を入力してください"
rescue ZeroDivisionError
  puts "0では割れません"
end

エラーの内容を受け取る(rescue => e)

begin
  value = Integer("abc")
rescue ArgumentError => e
  puts "エラー内容: #{e.message}"
  # エラー内容: invalid value for Integer(): "abc"
end

👉 rescue エラー名 => e と書くと、エラーの詳細情報がオブジェクト e に入りますe.message でメッセージ、e.class でエラーの種類を取り出せます。ログに残したり、原因を表示したりするときに使います。


4. else と ensure

  • else:begin例外が起きなかったときだけ実行される
  • ensure:例外の有無にかかわらず必ず実行される(後片付け用。他の言語の finally にあたる)
begin
  num = Integer("10")
rescue ArgumentError
  puts "変換に失敗しました"
else
  puts "変換に成功: #{num}"   # 例外がなかったときだけ
ensure
  puts "処理を終了します"       # 必ず実行される
end

5. メソッドの中では begin を省略できる

👉 メソッド定義(defend)の中では、begin を書かずに rescue を使えます。メソッド全体が begin のかわりになるイメージです。

def to_number(text)
  Integer(text)
rescue ArgumentError
  0   # 変換できないときは 0 を返す
end

puts to_number("42")    # 42
puts to_number("abc")   # 0

👉 Rubyのメソッド(def・引数・戻り値)についての記事はこちら


6. raise でわざと例外を出す

raise を使うと、自分で例外を発生させることができます。メソッドに渡された値がおかしいときなど、「これは想定外だ」と明示的に知らせたい場面で使います。

def set_age(age)
  raise ArgumentError, "年齢は0以上で指定してください" if age < 0
  age
end

puts set_age(20)   # 20
puts set_age(-5)   # ArgumentError: 年齢は0以上で指定してください
  • raise エラー名, "メッセージ":種類を指定して例外を出す
  • raise "メッセージ":種類を省略すると RuntimeError になる

7. 例外処理を使うときの注意

👉 「エラーを消すため」だけに例外処理を使うのは避けましょう。次のように何でもキャッチして何もしないと、本来直すべきバグまで隠れてしまい、原因がまったく分からなくなります。

# 悪い例:すべての例外を握りつぶしている
begin
  do_something
rescue => e
  # 何もしない
end
  • キャッチするエラーは具体的な種類を指定する(rescue ArgumentError など)
  • 例外処理は「起こりうると分かっていて、対処法があるエラー」に対して使う
  • 原因不明のエラーは、むしろ止まってくれたほうが気づける

8. よく出会うエラー一覧

エラー名起きる状況
NoMethodErrorその値に無いメソッドを呼んだ。nil に対して呼んでしまう例が多い
NameError定義していない変数・定数を使った
ArgumentError引数の個数が違う、Integer("abc") など値が不正
TypeError"文字" + 5 など、型に合わない操作
ZeroDivisionError整数を 0 で割り算した
KeyErrorhash.fetch(:x) で存在しないキーを指定した
Errno::ENOENT存在しないファイルを開こうとした

💡 配列の範囲外の番号(arr[100])やハッシュの無いキー(hash[:x])は、Rubyでは例外にならず nil が返ります。その nil に対してうっかりメソッドを呼んで NoMethodError になる、というのが初心者に一番多いパターンです。

👉 エラーメッセージは1行目が最も重要です。「どのファイルの何行目で、どのエラーが起きたか」が書かれているので、まずはそこを落ち着いて読みましょう。


9. まとめ

  • 例外が起きるとプログラムは停止する。begin・rescueで止まらずに対処できる
  • キャッチするエラーは種類を具体的に指定する(rescue ArgumentError)
  • rescue => eでエラーの詳細を受け取れる(e.message / e.class)
  • else=例外がなかったとき、ensure=必ず実行
  • メソッドの中では begin を省略できる。raiseで自分から例外を出せる
  • rescue Exceptionや何もしない rescue で握りつぶすのは避ける

👉 まずは Integer(gets.chomp)begin・rescue ArgumentError で囲むところから使ってみましょう。ユーザーの入力を扱うプログラムでは、ほぼ必ず登場するパターンです。

-Ruby
-, , , ,