Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails tips: コントローラでrescueする方法(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

2018/04/23: 初版公開
2022/01/27: 更新

Rails tips: コントローラでrescueする方法(翻訳)

Railsのコントローラでエラーをrescueしなければならないことがあります。クエリをかけたがデータベースにレコードがない場合にraiseされるActiveRecord::RecordNotFound例外をrescueする必要が生じることがほとんどでしょう。

サンプルのコントローラを作りましょう。

class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
  rescue ActiveRecord::RecordNotFound => e
    redirect_to :root, alert: 'User not found'
  end

  def edit
    @user = User.find(params[:id])
  rescue ActiveRecord::RecordNotFound => e
    redirect_to :root, alert: 'User not found'
  end
end

2つのメソッドがあり、どちらも同じ方法で例外を扱っています。このコードを使い回せるように、ActiveSupportモジュールのrescue_fromを使う方法があります。

class UsersController < ApplicationController
  rescue_from ActiveRecord::RecordNotFound do |exception|
    redirect_to :root, alert: 'User not found'
  end

  def show
    @user = User.find(params[:id])
  end

  def edit
    @user = User.find(params[:id])
  end
end

before_actionフィルタを使ってshowメソッドやeditメソッドもリファクタリングできますが、それはまたの機会に。さて、これでコントローラのコードが読みやすくなり、同じコードを2回書く必要がなくなりました。いいですね!以下のようにブロックの代わりにメソッド名を渡すこともできます。

class UsersController < ApplicationController
  rescue_from ActiveRecord::RecordNotFound, with: :redirect_to_homepage

  def show
    @user = User.find(params[:id])
  end

  def edit
    @user = User.find(params[:id])
  end

  protected

  def redirect_to_homepage
    redirect_to :root, alert: 'User not found'
  end
end

concernを使えば、1つのメソッドを複数のコントローラで使い回すことも可能です。これは、受け取った例外からrescueするロジックに依存します。rescue_fromは、エラー時にデフォルトの退屈なエラーページではなく、もっとましなページを表示したい場合にとても便利です。

お知らせ: RSpec & TDDの電子書籍を無料でダウンロード

もっと稼ぎたい方や会社をさらに発展させたい方へ: テスティングのスキルの重要性にお気づきでしょうか?テストを正しく書き始めることが、唯一のファーストステップです。無料でダウンロードいただける私の書籍『RSpec & Test Driven Developmentの無料ebook』をどうぞお役立てください。

関連記事

リファクタリングRuby: サブクラスをレジストリに置き換える(翻訳)

Service Objectがアンチパターンである理由とよりよい代替手段(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。