例えばあるデータをパースして、特定のデータのみデータベースに保存したいとする。
その中で、パースできない拡張子があればエラーが出て、処理が中断してしまいバグを引き起こしてしまう。
そこで、便利なのが例外処理というもので、処理を中断させず例外事案の場合の処理を施すことができる。
まさに、施すこされたら施し返す、恩返しです
を実現できるのだ。
今回は単純な計算を例に、例外処理を見ていこう。
#エラーが発生した場合の処理 begin / rescue
Ruby内で、10を0で割ろうとするとエラーが出てしまう。
puts 10 / 0
puts "こんにちわ"
divided by 0 (ZeroDivisionError)
処理が途中で、中断されてしまう。
そこで、
- エラーの対象になりそうな箇所を、
begin
で囲う。 - エラーが発生した時の処理を、
rescue
内に記述する。
begin
10 / 0
rescue
p "0で割れません"
end
puts "こんにちわ"
"0で割れません"
"こんにちわ"
処理が中断されず、エラー時の処理と正常処理どちらも実行された。
###省略法
beginなしで、rescueさせる
puts 10 / 0 rescue 0
puts 10 / nil rescue 0
0
0
#エラー内容を、変数に格納 rescue =>
begin
10 / 0
rescue => e
puts e
end
puts "こんにちわ"
divided by 0
こんにちわ
エラーオブジェクトが、変数eに格納されて出力できる。
#エラーごとの処理を変える rescue "エラーメッセージオブジェクト"
begin
10 / 0
rescue NoMethodError
puts "そのようなメソッドはない"
rescue ZeroDivisionError
puts "0で割れません"
end
0で割れません
2番目のエラーメッセージに該当するので、そのrescueに反応する。
###注意点
対象の例外クラスの親が、先に記述されいた場合はそちらが先に処理される
begin
10 / 0
rescue StandardError
puts "基本的なエラー"
rescue ZeroDivisionError
puts "0で割れません"
end
基本的なエラー
#明示的なエラーを発生させて、処理を中断させる raise
使用用途は、
- パラメータが想定されたものでないとき
- 不正なアクセスがきた時
begin
raise NoMethodError
rescue => e
p e
end
NoMethodError
###独自のエラーを発生させる
例外クラス(StandardErrorクラス)を継承させてあげる。
class Hoge < StandardError
end
begin
raise Hoge
rescue => e
p e
end
#<Hoge: Hoge>
#エラー時でも、再度初めから実行させる retry
num = 0
begin
puts 10 / num
rescue ZeroDivisionError => e
puts e
num = 1
retry
end
puts "終了しました"
divided by 0
10
終了しました
ループ1回目では、エラーが発生していて、
ループ2回目では、正常に処理がされている。
#エラーが発生しても、しなくても行う処理 ensure
begin
puts "例外なし"
rescue => e
puts e
ensure
puts "Hello"
end
例外なし
Hello
ensureは、いかなる時でも必ず実行される。
#番外編 エラーオブジェクトとは
begin
10 / 0
rescue => e
puts e.class
puts e.class.superclass
puts e.class.superclass.superclass
puts e.class.superclass.superclass.superclass
end
ZeroDivisionError
StandardError
Exception
Object
Exceptionが元となるクラスで、Objectがその親