Controller Callbacks (Filters)
Look at a typical books controller and four actions begin with the same line: find the book. Several also need the same check: is someone signed in? Copying these lines is how bugs creep in, when one action forgets the check. Callbacks run shared code for you, before or after the actions you choose.
The rule
before_action prepares or guards; a redirect inside it stops the action.
class BooksController < ApplicationController
before_action :require_member, except: [:index, :show]
before_action :set_book, only: [:show, :edit, :update, :destroy]
def show; end # @book is already set
def edit; end
def update
if @book.update(book_params)
redirect_to @book
else
render :edit, status: :unprocessable_entity
end
end
private
def set_book
@book = Book.find(params[:id])
end
def require_member
redirect_to new_session_path, alert: "Please sign in." unless current_member
end
endThe pieces:
before_actionruns before the action. Use it to load records or to guard access.after_actionruns after the action has produced its response — rarer, for things like logging.around_actionwraps the action and mustyieldto run it — for timing or transactions.only:andexcept:choose the actions.skip_before_actionturns an inherited callback off, for example a sign-in check defined inApplicationControllerthat the public home page should skip.
Callbacks run in the order they are declared, and parent-class callbacks run before the child's.
The halting rule: if a before_action renders or redirects, Rails stops there. Later callbacks and the action itself do not run.
The shortcut
Scan your actions for the same first line in more than one action. Loading → set_x with only:. Permission → a guard with except: for the public actions. Put the guard first so nothing is loaded for a visitor who will be turned away.
First callback
require_memberruns; there is no current member, so it redirects to the sign-in page.
The trap is a guard that only sets a flash message without redirecting. Nothing halts, and the action runs anyway.
Drills
Answer fast — trust the rule.
before_action :set_book, only: [:show] is declared. Does set_book run for index?
A before_action calls redirect_to root_path. What happens to the action?
ApplicationController requires sign-in for everything. How does PagesController#home stay public?
Which callback must call yield to let the action run?
Remember
- before_action prepares or guards; a render or redirect inside it stops the action.
- Shortcut: the same first line in several actions becomes a callback with only: or except:.
- Trap: a guard that warns but does not redirect lets the action run.
