3
1

More than 1 year has passed since last update.

【Ruby】例外処理の基礎について

Last updated at Posted at 2023-01-18

例外についてあまり使う機会がなかったので、簡単にまとめておきます。

例外とは

異常が発生したことを表すオブジェクト。
使用例としては、実行時に予想外のエラーが発生してプログラムが停止しないように、エラーを検知してプログラムの続きができるようになります。

例外を発生させる

Kernel.#raiseを使用すると、意図的にエラーを発生させることができます。
第一引数には例外クラスを指定する。第二引数には例外メッセージを指定します。

raise StandardError
raise StandardError, "error" #StandardError: error!
raise StandardError.new("error")
# それぞれの書き方があります

例外クラスの種類

上の例ではStandardErrorを発生させましたが、Rubyで定義されている例外クラスを用いていろいろなErrorを発生させることができます。

raise StandardError, "error!" # => StandardError: error!
raise RuntimeError, "error!"  # => RuntimeError: error!
raise SyntaxError, "error!"   # => SyntaxError: error!

例外の種類については組込みライブラリ-例外を参照してください。

また、エラーメッセージだけを記載して定義することができますが、この時のエラーの補足はRuntimeErrorになります。

初期値はRuntimeErrorだということを覚えておきます。

raise "error!" # => RuntimeError

beginを使ってエラーを取得

begin~rescueでエラーが発生する可能性のある処理を定義
rescue~endでエラーが発生した時の処理を定義します。

begin
  # 実行するコード定義
rescue
  # エラー時の処理を定義
end

また、elseensureを定義して、エラーが発生しなかった時の定義と、エラーに関わらず実行される処理を定義することができます。

begin
  # 実行するコード定義
rescue
  # エラー時の処理を定義
else
  # エラーが発生しなかった時の処理を定義
ensure
  # エラーに関わらず実行される処理を定義
end

簡単な例を挙げます。

begin
  p 3/3
rescue
  p "error!"
else
  p "no error!"
ensure
  p "プログラムが処理されました"
end

# => 1
# => "no error!" 
# => "プログラムが処理されました"

rescureでエラーの情報を取得

rescure => 変数名でエラーの情報を取得することができます

sample.rb
begin
  p 3/0
rescue => e
  p e.class     # 例外の種類を出力
  p e.message   # 例外のメッセージを出力
  p e.backtrace # 例外が発生した位置情報を出力
end

# => ZeroDivisionError
# => "divided by 0"
# => ["sample.rb:2:in `/'", "sample.rb:2:in `<main>'"]

rescueでエラー毎に例外クラスを指定

rescueの後に、例外のクラスを指定して、それぞれの例外のケースに合わせて処理を変えることもできます。
@okuramasafumiさんのコメントより修正

begin
  p 3/0
rescue ZeroDivisionError
  puts "ゼロでは割れません"
rescue StandardError
  puts "エラーが発生しました"
end
# => "ゼロでは割れません"が表示される

また、上から順番に定義した例外クラスとマッチしたものから止まるようになります。

begin
  p 3/0
rescue StandardError
  puts "エラーが発生しました"
rescue ZeroDivisionError
  puts "ゼロでは割れません"
end
# => "エラーが発生しました"が表示される

raiseとbeginを組み合わせてみる

raiseでは例外を発生させることができるとお伝えしました。
begin~rescueに定義して実際に例外が発生して、取得できているか確認します。

begin 
  raise ZeroDivisionError.new("Error!")
rescue => e
  p e.class      #=> ZeroDivisionError
  p e.message    #=> "Error!"
  p e.backtrace  #=> "sample.rb:2:in `<main>'"
end

Retryで処理を再実行

rescue~endretryを使用することで処理を再度実行することができる。
@okuramasafumiさんのコメントより修正

count = 0

begin
  p 3/0
rescue
  p count += 1   
  if count < 2
    retry
  end

  p "error"
end

# => 1
# => 2
# => "error"

参照

3
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1