Ruby
Rails

rails: before_actionとは

More than 1 year has passed since last update.

*scivolaさんよりいただいたコメントを参考に冒頭箇所一部編集しました。

before_actionとは

Action Controller Overviewによるとbefore_actionはフィルタリングとして定義されている。

if you set a filter on ApplicationController, it will be run on every controller in your application.
コントローラー上に(before_actionを始めとした)フィルタリングを含めればアプリケーション起動時に毎回作動してくれる。
ApplicationControllerに定義することによってアクション実行前に全てのコントローラーにフィルターがかかる。(scivola)

使用例

実装例の主な例としてユーザー認証などがそれに当たる:

class ApplicationController < ActionController::Base
  before_action :require_login

  private

  def require_login
    unless logged_in?
      flash[:error] = "You must be logged in to access this section"
      redirect_to new_login_url # halts request cycle
    end
  end
end

コントローラーに新たにbefore_actionを追加することによってrequire_loginアプリケーション起動時(すでに定義されている各アクションの実行前)に作動してくれる。全てのユーザーから登録しているユーザーだけをフィルタリングしている。

onlyとexcept

しかし上のように表記してしまうと全てのページ移動においてユーザー認証を要する実装になってしまうので例えば新規会員登録したいユーザーにすら認証が入ってきてしまうというダブルバインディングな構造になってしまう。

For obvious reasons (the user wouldn't be able to log in in the first place!), not all controllers or actions should require this. You can prevent this filter from running before particular actions with skipbefore_action:

class LoginsController < ApplicationController
  skip_before_action :require_login, only: [:new, :create]
end

対策として新規登録といったページではユーザー認証を任意的になくすことができる。only: [:new, :create]がそれに当たる。

The :only option is used to skip this filter only for these actions, and there is also an :except option which works the other way.
onlyexceptは特定のフィルタリングをスキップさせたいときに使用する。

まとめ

まとめるとbefore_actionの役割は以下の通り:

  • コントローラーに入れておけばアプリケーション起動時(すでに定義されているアクションが実行される前)に自動で作動してくれるフィルタリング。アクションの中身が重複していて且つ仕様頻度が高い場合はbefore_actionとして定義しておいたほうが効率よくコードの見栄えが良くなる。

  • onlyexceptを使えばより柔軟な実装も可能。