こんにちは、エンジニアのさもです。
2回目にしていきなり例外処理です。しかもQAじゃないです(笑)
入門したては、ガンガン機能を追加していき、サイトを作りこんで行きたいかと思うのですが、少し立ち止まって、例外処理について学んで下さい。
一度書くと、次に作るときにコピペでOKです!
スポンサーリンク
目次
Railsにおける例外処理とは?
Javaなどのプログラミング言語でも例外を投げる、キャッチする。なんて言いますよね。
Rubyにもraise, rescueという例外に関する仕様はあるのですが、今回はRailsで例外発生時の挙動をどうするか、について書いていきます。
webサイトを良く見る方は、「404 Not Found」みたいなページを見たことがあるでしょうか?URLが間違っていたり、久しぶりに訪れたらサイトが無くなっていたなんてときに表示されるページです。
「404」というのはwebページへアクセスしたときに、コンテンツと一緒についてくる、「HTTPステータスコード」の一つです。
正常にページが見れるときは、200が割り当てられています。サーバに障害があったときは、500が返ってきたりします。
詳しくはこちら
404はただのコードなので、webページの場合は、返ってきてもどうしようもないですよね。だから404ページと言われるものを返します。
自分でwebサイトを作るときも、間違ったURLにアクセスされたとき用に404ページは作っておかなければなりません。
それ以外に、例えば、/users/1 のように、idが1のユーザにアクセスするURLがあるとします。このとき、存在しないユーザーIDへアクセス(/users/999)した場合にも404ページを返さなくてはいけません。
なぜなら、RailsはRestful、つまりURLとリソースが1対1で結びついているからです。リソースというと、/views/users/show.html.erb
のことを思い浮かべるかもしれませんが、実際は、「idが1のユーザー」の事を指しています。htmlファイルはあくまでも、リソースを見やすく整形したものです。
そのため、「/users/存在しないユーザーID」にアクセスされたときは、対応するリソース(ユーザー)が存在しないので、ページが存在しないという情報を返さなくてはなりません。この情報が、404ページであり、ステータスコード404です。
例外の発生方法
例外処理の基本は、例外が発生(raise)ー>例外をキャッチ(rescue)です。
まずは例外の発生について書いていきましょう。
具体的にどのように実装するのか、ですが、実はとても簡単です。
最も基本的な例ですが、UsersController#show
で、存在しないユーザIDが指定された場合について考えましょう。
class UsersController < ApplicationController before_action :set_user, only: [:edit, :update, :show, :destroy] # index等省略 def show end private def set_user @user = User.find(params[:id]) end end
はい、完了です。
いつもどおりのコントローラですね。
どこで例外が発生するかわかりますか?
正解は、find
メソッドです。
find
メソッドは、引数で渡したIDのユーザが存在しない場合に、ActiveRecord::RecordNotFound
という名前の例外を発生させます。
試しに、rails consoleで「User.find(999)」と打ってみてください(モデルはお使いの環境に合わせて、存在しているモデルに変えてください)。ActiveRecord::RecordNotFound
と表示されるはずです。
例外のキャッチの仕方
何もしません(笑)
404エラーや500, 422エラーの場合は、Railsがよしなにやってくれます。
表示されるエラーページ自体はpublicフォルダにあります。
ただし、デフォルトのエラーページは味気ないので、かっこよくカスタマイズしたい場合は、public/404.htmlなど、対応するhtmlファイルを編集すればOKです。
自分で例外を発生させる
ActiveRecord::RecordNotFound
の場合には自動的に例外を投げてくれましたが、「自分のサイトではこういう場合に404を発生させて、404ページを表示したいんだ」ということがあります。
そんなときは以下のようにします。(例えば、ユーザのemailカラムが未入力の場合に、まだユーザが存在していないかのように見せたいとき。)
class UsersController < ApplicationController before_action :set_user, only: [:edit, :update, :show, :destroy] # index等省略 def show raise ActiveRecord::RecordNotFound.new("お試し例外だよ") if @user.email.nil? end private def set_user @user = User.find(params[:id]) end end
show
アクションに1行追加しました。
raise
メソッドは、第一引数の例外を発生させるKernelクラスのメソッドです。
ちなみに、raise
メソッドに文字列を渡すと、その文字列をメッセージとしたRuntimeError
例外を発生させます。
すべての例外に対応する
ActiveRecord::RecordNotFound
をはじめ、例外はたくさんあります。そこで、用意している例外以外の例外に対応するために、
復旧可能な実行時エラーの親クラスである、StandardError
に対してrescue
します。
エラーキャッチの定義は、application_controller.rbに書きます。
class ApplicationController < ActionController::Base rescue_from StandardError, with: :rescue_exeption def rescue_exeption(e = nil) if e logger.info "StandardError!: #{e.message}" logger.info e.backtrace.join("\n") end redirect_to root_path end end
このように書いておくと、Railsが拾わなかった例外を、rescue_exeption
メソッドが処理してくれるようになります。rescue_exeption
内では、エラー原因特定やデバッグのために、出来るだけ多くの情報を残しましょう。
Bagsnagというサービスを利用して、開発者へ通知するなどの処理を含めるのも有効です。
参考
より詳しく勉強したいという方のために、オススメの書籍を紹介します
- ステータスコードやURLをどう設計するかなど、Rialsでも役に立つ知識がいっぱい載っています。

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)
- 作者: 山本陽平
- 出版社/メーカー: 技術評論社
- 発売日: 2010/04/08
- メディア: 単行本(ソフトカバー)
- 購入: 143人 クリック: 4,320回
- この商品を含むブログ (183件) を見る
- 定評のあるRails本

Ruby on Rails 5アプリケーションプログラミング
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2017/04/14
- メディア: 大型本
- この商品を含むブログを見る

Ruby on Rails 4 アプリケーションプログラミング
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2014/04/11
- メディア: 大型本
- この商品を含むブログ (6件) を見る
- 最近出たRubyの本(チェリー本)すごくいい!先行販売してたので買いました。

プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで (Software Design plusシリーズ)
- 作者: 伊藤淳一
- 出版社/メーカー: 技術評論社
- 発売日: 2017/11/25
- メディア: 大型本
- この商品を含むブログを見る
- Railsの例外について、とてもよくまとまっているエントリーです。
最後に
以上、Railsの例外処理でした。
いかなるユーザの操作に対しても応答できるwebサービスを目指して、ぜひ例外処理を書いてみてください。
読者登録をしていただけると、ブログを続ける励みになりますので、よろしくお願いします。