Skip to content

Commit

Permalink
Make after_filter halt when before_filter renders or redirects [#5648
Browse files Browse the repository at this point in the history
…state:resolved]

Signed-off-by: José Valim <jose.valim@gmail.com>
  • Loading branch information
marklazz authored and josevalim committed Nov 11, 2010
1 parent 7846fb7 commit 2bb1c20
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 2 deletions.
2 changes: 2 additions & 0 deletions actionpack/lib/abstract_controller/callbacks.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def _insert_callbacks(callbacks, block)
# for details on the allowed parameters. # for details on the allowed parameters.
def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk) def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk)
_insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options} _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options}
options[:if]=(Array.wrap(options[:if]) << "!halted") if #{filter == :after}
set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before_filter, name, options) set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before_filter, name, options)
end # end end # end
end # end end # end
Expand All @@ -91,6 +92,7 @@ def #{filter}_filter(*names, &blk)
# for details on the allowed parameters. # for details on the allowed parameters.
def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk) def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk)
_insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
options[:if]=(Array.wrap(options[:if]) << "!halted") if #{filter == :after}
set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true)) set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true))
end # end end # end
end # end end # end
Expand Down
81 changes: 79 additions & 2 deletions actionpack/test/controller/filters_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -78,17 +78,68 @@ class TestMultipleFiltersController < ActionController::Base
end end


class RenderingController < ActionController::Base class RenderingController < ActionController::Base
before_filter :render_something_else before_filter :before_filter_rendering
after_filter :unreached_after_filter


def show def show
@ran_action = true @ran_action = true
render :inline => "ran action" render :inline => "ran action"
end end


private private
def render_something_else def before_filter_rendering
@ran_filter ||= []
@ran_filter << "before_filter_rendering"
render :inline => "something else" render :inline => "something else"
end end

def unreached_after_filter
@ran_filter << "unreached_after_filter_after_render"
end
end

class RenderingForPrependAfterFilterController < RenderingController
prepend_after_filter :unreached_prepend_after_filter

private
def unreached_prepend_after_filter
@ran_filter << "unreached_preprend_after_filter_after_render"
end
end

class BeforeFilterRedirectionController < ActionController::Base
before_filter :before_filter_redirects
after_filter :unreached_after_filter

def show
@ran_action = true
render :inline => "ran show action"
end

def target_of_redirection
@ran_target_of_redirection = true
render :inline => "ran target_of_redirection action"
end

private
def before_filter_redirects
@ran_filter ||= []
@ran_filter << "before_filter_redirects"
redirect_to(:action => 'target_of_redirection')
end

def unreached_after_filter
@ran_filter << "unreached_after_filter_after_redirection"
end
end

class BeforeFilterRedirectionForPrependAfterFilterController < BeforeFilterRedirectionController
prepend_after_filter :unreached_prepend_after_filter_after_redirection

private
def unreached_prepend_after_filter_after_redirection
@ran_filter << "unreached_prepend_after_filter_after_redirection"
end
end end


class ConditionalFilterController < ActionController::Base class ConditionalFilterController < ActionController::Base
Expand Down Expand Up @@ -625,6 +676,32 @@ def test_rendering_breaks_filtering_chain
assert !assigns["ran_action"] assert !assigns["ran_action"]
end end


def test_before_filter_rendering_breaks_filtering_chain_for_after_filter
response = test_process(RenderingController)
assert_equal %w( before_filter_rendering ), assigns["ran_filter"]
assert !assigns["ran_action"]
end

def test_before_filter_redirects_breaks_filtering_chain_for_after_filter
response = test_process(BeforeFilterRedirectionController)
assert_response :redirect
assert_equal "http://test.host/filter_test/before_filter_redirection/target_of_redirection", redirect_to_url
assert_equal %w( before_filter_redirects ), assigns["ran_filter"]
end

def test_before_filter_rendering_breaks_filtering_chain_for_preprend_after_filter
response = test_process(RenderingForPrependAfterFilterController)
assert_equal %w( before_filter_rendering ), assigns["ran_filter"]
assert !assigns["ran_action"]
end

def test_before_filter_redirects_breaks_filtering_chain_for_preprend_after_filter
response = test_process(BeforeFilterRedirectionForPrependAfterFilterController)
assert_response :redirect
assert_equal "http://test.host/filter_test/before_filter_redirection_for_prepend_after_filter/target_of_redirection", redirect_to_url
assert_equal %w( before_filter_redirects ), assigns["ran_filter"]
end

def test_filters_with_mixed_specialization_run_in_order def test_filters_with_mixed_specialization_run_in_order
assert_nothing_raised do assert_nothing_raised do
response = test_process(MixedSpecializationController, 'bar') response = test_process(MixedSpecializationController, 'bar')
Expand Down

0 comments on commit 2bb1c20

Please sign in to comment.