railsの例外処理の扱いについて
お久しぶりです!
サーバエンジニアの井出です!
メインはPHPですが
最近railsに触れる機会多くなったので
今日はrailsの例外処理について
まとめようと思います。
例外処理とは
処理中に何かしらの理由でエラー発生した際の処理になります。
どんなシステムでもエラーは起きるもので
発生した際にどのような処理を行うかによって
調査などもしやすくなるものです。
railsの例外処理に使用するのは主に以下になります。
- begin
- rescue
- retry
- raise
- ensure
begin、rescueについて
基本的な使用方法は以下のように
beginで始まり、rescueでエラー発生した時の処理を記載します。
1 2 3 4 5 6 7 |
hoge = nil begin hoge = hoge + 1 p "正常" rescue p "エラーですよ" end |
これを実行すると以下の結果になります。
1 |
エラーですよ |
が出力されました。
hogeはnilなのでメモリに確保されていない変数になるため
加算したところエラーとなり、rescueの処理が走りました。
エラーの中身を詳しく知りたい場合は
rescue => e
とすると、エラー内容がeに入ります。
1 2 3 4 5 6 7 |
hoge = nil begin hoge = hoge + 1 p "正常" rescue => e puts e end |
これを実行すると以下の結果になります。
1 |
#<NoMethodError: undefined method + for nil:NilClass> |
エラーの内容分かりやすくていいですね!
さらにエラーごとにrescueの例外処理を指定できるので
上記のエラーの場合に対しては、以下のような記載も可能になります。
1 2 3 4 5 6 7 8 9 |
hoge = nil begin hoge = hoge + 1 p "正常" rescue NoMethodError puts "メソッドが存在しない" rescue => e p "それ以外のエラー" end |
先ほどのエラーを見ると「NoMethodError」をいう内容になっていました。
その場合のエラー処理を書く場合は、rescue NoMethodError
とすると
記載可能となります。
retryについて
次はretryの説明になります。
名前からして察しが付くかもしれませんが
例外発生時に再度処理を行うための機能になります。
では実際にソースをみて行きましょう。
1 2 3 4 5 6 7 8 9 10 11 |
hoge = nil begin hoge = hoge + 1 p "正常" rescue NoMethodError puts "メソッドが存在しない" hoge = 1 # hogeに値を設定したのでnilでは無くなる retry #beginブロックを再度実行する rescue => e p "それ以外のエラー" end |
先ほどの、処理をそのまま使用する形で
rescue内に加え、retry処理を実行しました。
これを実行すると以下の結果になります。
1 2 |
メソッドが存在しない 正常 |
実行結果の通り一度例外処理に入りましたが
hogeに値を設定し、nilではない状態にしretryで再度beginの処理を実行し
無事、正常処理になりました。
このように一度はエラーになったが何かしらの手を加えて
再度実行させるときなどに便利です。
以前使用した時は、ページアクセス時にpvを計測する処理で
ページ初期アクセス時はレコードが存在しないのでinsert、
2回目以降は存在しているのでupdateを実現したく
同時アクセス時はinsertが同時2回走りprimaryエラーとなるため
こちらのretry処理を駆使して実現させました。
同時アクセス時はどちらかが重複エラーとなるため
retryすることにより、レコードが存在している状態になるため
updateが走り、無事実現ができました。
raiseについて
raiseは任意で例外処理を発生させることができます。
必須項目不足などのバリエーションのエラー時などに
メインで使うかと思いますが、こちらもソースで確認してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
hoge = nil begin p "処理開始前1" raise NoMethodError p "処理開始前2" hoge = hoge + 1 p "正常" rescue NoMethodError puts "メソッドが存在しない" rescue => e p "それ以外のエラー" end |
raise NoMethodError
を指定することにより
NoMethodErrorの例外処理を発生させ
rescue NoMethodError
の処理が走ります
これを実行すると以下の結果になります。
1 2 |
処理開始前1 メソッドが存在しない |
ensureについて
例外の有無に関係なく必ず実行される処理になります。
使用用途としては、あまりないかもですがDBのテーブルロックをする処理があり解除が必要、
ファイルオープンしていてクローズの処理が必要などになります・
記述方法としては以下になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
hoge = nil begin p "処理開始前1" raise NoMethodError p "処理開始前2" hoge = hoge + 1 p "正常" rescue NoMethodError puts "メソッドが存在しない" rescue => e p "それ以外のエラー" ensure p "必ず実行" end |
これを実行すると以下の結果になります。
1 2 3 |
処理開始前1 メソッドが存在しない 必ず実行 |
実行されましたね!
railsは勉強すればするほど
便利なものが多く凄くやりがいがある言語です!
セイコロンや()が無くても動作するなど
特殊な記法になれない部分もありますが
それも含めて味があるなと最近思うようになってきたので
日々勉強して、色々学んでいこうと思います!
また何か見つけたらここにまとめようと思います!
ご覧いただきありがとうございました!