Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Controllers  ›  Lesson

Controller Callbacks (Filters)

Controller Callbacks (filters) 12 minbefore_action, after_action and around_action run shared code around actions, and a before_action that renders or redirects stops the action from running.

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
end

The pieces:

  • before_action runs before the action. Use it to load records or to guard access.
  • after_action runs after the action has produced its response — rarer, for things like logging.
  • around_action wraps the action and must yield to run it — for timing or transactions.
  • only: and except: choose the actions.
  • skip_before_action turns an inherited callback off, for example a sign-in check defined in ApplicationController that 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.

A guest opens /books/7/editStep 1 of 4
  1. First callback

    require_member runs; 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.

quick drill

before_action :set_book, only: [:show] is declared. Does set_book run for index?

quick drill

A before_action calls redirect_to root_path. What happens to the action?

quick drill

ApplicationController requires sign-in for everything. How does PagesController#home stay public?

quick drill

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.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainRemove the repetition

In BooksController, show, edit, update and destroy each start with @book = Book.find(params[:id]), and only signed-in members may create, edit, update or destroy. Rewrite this with callbacks and explain what happens when a guest tries to edit.