before_filterでfalse返しているのにアクションが実行されるコトがある

以前ちょろーっと読んだ本には「before_filterに指定したブロックやメソッドが評価された結果, falseを返した場合, フィルターのチェインはそこで終わるよ!」って書いてあった(と思う).

それを信じてやってみたら, なんとチェインが終わらない(そのままアクションが実行される)!

class HogeController
  before_filter :fuga

  private

  def fuga
    false
  end
end

終わらないのはボクの記憶違いなのか, それともRailsのバージョンによるものなのか…… そしてふと思う. チェインが終わった時点でレスポンス(render, redirect_to)が決まっていないときはどうなるんだろう, って. あー, なんとなくわかったような……

そしてrenderしてみる.

class HogeController
  before_filter :fuga

  private

  def fuga
    render
    false
  end
end

お, 止まった! いまさらながらにソースを見てみる.

# actionpack-2.3.2/lib/action_controller/filters.rb
# 略
def call_filters(chain, index, nesting)
  index = run_before_filters(chain, index, nesting)
  aborted = @before_filter_chain_aborted
  perform_action_without_filters unless performed? || aborted
  return index if nesting != 0 || aborted
  run_after_filters(chain, index)
end
# 略

(あんまり詳しく見ていないのでおそらくだけど)perform_action_without_filtersがアクションのみの実行だと思う. そしてそれを実行する条件にperformed?(レスポンスが決定しているかどうか)が含まれているからかなぁ. てかperformed?がtrueの時点でアクションを実行しないのなら, falseを返す必要ないんじゃない?

というコトで下記のコードでもアクションは実行されないようです.

class HogeController
  before_filter :fuga

  private

  def fuga
    render
  end
end

でもbefore_filterが多重に定義されていたらどうなるかは細かく試していないです(ちょろっと試した感じでは止まっていたと思いますけども……).