37

I am reading the "Agile Web Development with Rails 4", on pag. 338 it says:

[...] Callbacks can be passive, monitoring activity performed by a controller. They can also take a more active part in request handling. If a before action callback returns false, then processing of the callback chain terminates, and the action is not run. [...]

Now my doubt is the following: here how to execute an action if the before_action returns false it was told that the goal of the before_action is to prepare something before the action is executed, if it returns false it doesn't mean that the action is not run, but according the book it is right so...so I am getting a little bit confused.

If I'm trying the following

class ProductsController < ApplicationController
before_action :test

  def index
    @products = Product.all
  end


  private

    def test
      return false
    end
end

But the action is executed, when I call /products I do not get any error and the page shows up just fine

Community
  • 1
  • 1
zer0uno
  • 7,521
  • 13
  • 57
  • 86

1 Answers1

63

before_action (formerly named before_filter) is a callback that is performed before an action is executed. You can read more about controller before/after_action.

It is normally used to prepare the action or alter the execution.

The convention is that if any of the methods in the chain render or redirect, then the execution is halted and the action is not rendered.

before_action :check_permission

def hello
end

protected

def check_permission
  unless current_user.admin?
    # head is equivalent to a rendering
    head(403)
  end
end

In this example, if current_user.admin? returns false, the hello action is never performed.

The following one, instead, is an example of action setup:

before_action :find_post

def show
  # ...
end

def edit
  # ...
end

def update
  # ...
end

protected

def find_post
  @post = Post.find(params[:id])
end

In this case find_post will never return false. In fact, the purpose of this before_action is to extract a shared command from the body of the actions.

About returning false, as far as I know this is true for ActiveRecord callbacks. But for a before_action, returning false has no effect. In fact, the return value is not mentioned as important in the official documentation.

DaveMongoose
  • 875
  • 9
  • 15
Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
  • 1
    if `hello` is never performed what is performed? – zer0uno Dec 17 '13 at 00:23
  • I've updated the example to be more explicit. In this case, the request return 403. – Simone Carletti Dec 17 '13 at 00:26
  • 1
    As far as I know, return `false` is not stopping the action. It stops updates in ActiveRecord callbacks. The official documentation does not mention the case of `false`. I assume the book may be wrong or referencing a behavior that changed before the final release. – Simone Carletti Dec 17 '13 at 00:32
  • 14
    the book (as reported) is wrong. What stops the action is a render in the handler, such as a `redirect` or a `head`. The engine detects the web hit is satisfied, and stops the parade. – Phlip Dec 17 '13 at 00:43
  • 2
    This answer should be updated now. As in the latest Rails version, only return `false` for ActiveRecord callbacks will not break the execution now. You need to `throw(:abort)` explicitly. – hiveer Jun 15 '20 at 01:24