Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 7984

Show
Ignore:
Timestamp:
10/21/07 18:58:17 (11 months ago)
Author:
david
Message:

Changed before_filter halting to happen automatically on render or redirect but no longer on simply returning false [DHH]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r7978 r7984  
    11*SVN* 
     2 
     3* Changed before_filter halting to happen automatically on render or redirect but no longer on simply returning false [DHH] 
    24 
    35* Ensure that cookies handle array values correctly.  Closes #9937 [queso] 
  • trunk/actionpack/lib/action_controller/filters.rb

    r7719 r7984  
    88    end 
    99 
    10     # Filters enable controllers to run shared pre and post processing code for its actions. These filters can be used to do 
     10    # Filters enable controllers to run shared pre- and post-processing code for its actions. These filters can be used to do 
    1111    # authentication, caching, or auditing before the intended action is performed. Or to do localization or output 
    1212    # compression after the action has been performed. Filters have access to the request, response, and all the instance 
     
    3737    # 
    3838    # Now any actions performed on the BankController will have the audit method called before. On the VaultController, 
    39     # first the audit method is called, then the verify_credentials method. If the audit method returns false, then 
     39    # first the audit method is called, then the verify_credentials method. If the audit method renders or redirects, then 
    4040    # verify_credentials and the intended action are never called. 
    4141    # 
     
    6666    # 
    6767    #   class WeblogController < ActionController::Base 
    68     #     before_filter { |controller| false if controller.params["stop_action"] } 
     68    #     before_filter { |controller| head(400) if controller.params["stop_action"] } 
    6969    #   end 
    7070    # 
     
    9191    # 
    9292    # The filter chain for the CheckoutController is now <tt>:ensure_items_in_cart, :ensure_items_in_stock,</tt> 
    93     # <tt>:verify_open_shop</tt>. So if either of the ensure filters return false, we'll never get around to see if the shop 
     93    # <tt>:verify_open_shop</tt>. So if either of the ensure filters renders or redirects, we'll never get around to see if the shop 
    9494    # is open or not. 
    9595    # 
     
    143143    # 
    144144    #   class Authorizer 
    145     #     # This will run before the action. Returning false aborts the action. 
     145    #     # This will run before the action. Redirecting aborts the action. 
    146146    #     def before(controller) 
    147     #       if user.authorized? 
    148     #         return true 
    149     #       else 
    150     #         redirect_to login_url 
    151     #         return false 
     147    #       unless user.authorized? 
     148    #         redirect_to(login_url) 
    152149    #       end 
    153150    #     end 
    154151    # 
    155     #     # This will run after the action if and only if before returned true
     152    #     # This will run after the action if and only if before did not render or redirect
    156153    #     def after(controller) 
    157154    #     end 
     
    159156    # 
    160157    # If the filter has before and after methods, the before method will be 
    161     # called before the action. If before returns false, the filter chain is 
     158    # called before the action. If before renders or redirects, the filter chain is 
    162159    # halted and after will not be run. See Filter Chain Halting below for 
    163160    # an example. 
     
    219216    # before a controller action is run. This is useful, for example, to deny 
    220217    # access to unauthenticated users or to redirect from http to https. 
    221     # Simply return false from the filter or call render or redirect. 
    222     # After filters will not be executed if the filter chain is halted. 
     218    # Simply call render or redirect. After filters will not be executed if the filter  
     219    # chain is halted. 
    223220    # 
    224221    # Around filters halt the request unless the action block is called. 
     
    245242    # 
    246243    # If #around returns before yielding, #after will still not be run. The #before 
    247     # filter and controller action will not be run. If #before returns false
     244    # filter and controller action will not be run. If #before renders or redirects
    248245    # the second half of #around and will still run but #after and the 
    249246    # action will not. If #around fails to yield, #after will not be run. 
     
    442439        def run(controller) 
    443440          # only filters returning false are halted. 
    444           if false == @filter.call(controller) 
    445             controller.send! :halt_filter_chain, @filter, :returned_false 
     441          @filter.call(controller) 
     442          if controller.send!(:performed?) 
     443            controller.send!(:halt_filter_chain, @filter, :rendered_or_redirected) 
    446444          end 
    447445        end 
     
    658656          return filter unless filter_responds_to_before_and_after(filter) 
    659657          Proc.new do |controller, action| 
    660             if filter.before(controller) == false 
    661               controller.send! :halt_filter_chain, filter, :returned_false 
     658            filter.before(controller) 
     659 
     660            if controller.send!(:performed?) 
     661              controller.send!(:halt_filter_chain, filter, :rendered_or_redirected) 
    662662            else 
    663663              begin 
     
    711711          filter, index = skip_excluded_filters(chain, index) 
    712712          break unless filter # end of call chain reached 
     713 
    713714          case filter.type 
    714715          when :before 
     
    718719          when :around 
    719720            yielded = false 
     721 
    720722            filter.call(self) do 
    721723              yielded = true 
     
    723725              index = call_filters(chain, index.next, nesting.next) 
    724726            end 
     727 
    725728            halt_filter_chain(filter, :did_not_yield) unless yielded 
     729 
    726730            break 
    727731          else 
     
    729733          end 
    730734        end 
     735 
    731736        index 
    732737      end 
     
    734739      def run_after_filters(chain, index) 
    735740        seen_after_filter = false 
     741 
    736742        while chain[index] 
    737743          filter, index = skip_excluded_filters(chain, index) 
    738744          break unless filter # end of call chain reached 
     745 
    739746          case filter.type 
    740747          when :after 
     
    745752            raise ActionControllerError, "filter #{filter.inspect} was in the wrong place!" if seen_after_filter 
    746753          end 
     754 
    747755          index = index.next 
    748756        end 
     757 
    749758        index.next 
    750759      end 
  • trunk/actionpack/test/controller/filters_test.rb

    r7719 r7984  
    4545      define_method "try_#{i}" do 
    4646        instance_variable_set :@try, i 
    47         action_name != "fail_#{i}" 
     47        if action_name == "fail_#{i}" 
     48          head(404) 
     49        end 
    4850      end 
    4951    end 
     
    824826    controller = ::FilterTest::TestMultipleFiltersController.new 
    825827    response = test_process(controller, 'fail_1') 
    826     assert_equal '', response.body 
     828    assert_equal ' ', response.body 
    827829    assert_equal 1, controller.instance_variable_get(:@try) 
    828830    assert controller.instance_variable_get(:@before_filter_chain_aborted) 
     
    832834    controller = ::FilterTest::TestMultipleFiltersController.new 
    833835    response = test_process(controller, 'fail_2') 
    834     assert_equal '', response.body 
     836    assert_equal ' ', response.body 
    835837    assert_equal 2, controller.instance_variable_get(:@try) 
    836838    assert controller.instance_variable_get(:@before_filter_chain_aborted) 
     
    840842    controller = ::FilterTest::TestMultipleFiltersController.new 
    841843    response = test_process(controller, 'fail_3') 
    842     assert_equal '', response.body 
     844    assert_equal ' ', response.body 
    843845    assert_equal 3, controller.instance_variable_get(:@try) 
    844846    assert controller.instance_variable_get(:@before_filter_chain_aborted)