*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 skip_before_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.
onlyとexceptは特定のフィルタリングをスキップさせたいときに使用する。
まとめ
まとめるとbefore_actionの役割は以下の通り:
-
コントローラーに入れておけば
アプリケーション起動時(すでに定義されているアクションが実行される前)に自動で作動してくれるフィルタリング。アクションの中身が重複していて且つ仕様頻度が高い場合はbefore_actionとして定義しておいたほうが効率よくコードの見栄えが良くなる。 -
onlyやexceptを使えばより柔軟な実装も可能。