*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
を使えばより柔軟な実装も可能。