Changeset 1051

Show
Ignore:
Timestamp:
11/25/07 19:10:03 (1 year ago)
Author:
e.@brainspl.at
Message:

adds skip_beofre and skip_after for beofre and after filter chains. Thanks CptOatmeal?

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/lib/merb/abstract_controller.rb

    r1047 r1051  
    184184    #  
    185185    def self.before(filter, opts={}) 
    186       raise(ArgumentError, 
    187         "You can specify either :only or :exclude but  
    188          not both at the same time for the same filter." 
    189       ) if opts.has_key?(:only) && opts.has_key?(:exclude) 
    190        
    191       opts = shuffle_filters!(opts) 
    192        
    193       case filter 
    194       when Symbol, String, Proc 
    195         (self.before_filters ||= []) << [filter, opts] 
    196       else 
    197         raise(ArgumentError,  
    198           'filters need to be either a Symbol, String or a Proc' 
    199         )         
    200       end   
     186      add_filter((self.before_filters ||= []), filter, opts) 
    201187    end 
    202188     
     
    208194    # gain access to the response body like so: after Proc.new {|c| 
    209195    # Tidy.new(c.body) }, :only => :index 
     196     
    210197    def self.after(filter, opts={}) 
     198      add_filter((self.after_filters ||= []), filter, opts) 
     199    end 
     200     
     201    # Call #skip_before to remove an already declared (before) filter from your controller. 
     202    #  
     203    # Example: 
     204    #   class Application < Merb::Controller 
     205    #     before :require_login 
     206    #   end 
     207    # 
     208    #   class Login < Merb::Controller 
     209    #     skip_before :require_login  # Users shouldn't have to be logged in to log in 
     210    #   end 
     211     
     212    def self.skip_before(filter) 
     213      skip_filter((self.before_filters || []), filter) 
     214    end 
     215     
     216    # Exactly like #skip_before, but for after filters 
     217     
     218    def self.skip_after(filter) 
     219      skip_filter((self.after_filters || []), filter) 
     220    end 
     221     
     222    def self.default_thrown_content 
     223      Hash.new{ |hash, key| hash[key] = "" } 
     224    end 
     225     
     226    # Set here to respond when rendering to cover the provides syntax of setting the content_type 
     227    def content_type_set? 
     228      false 
     229    end 
     230 
     231    def content_type 
     232      params[:format] || :html 
     233    end 
     234     
     235  private 
     236 
     237    def self.add_filter(filters, filter, opts={}) 
    211238      raise(ArgumentError, 
    212239        "You can specify either :only or :exclude but  
    213240         not both at the same time for the same filter." 
    214241      ) if opts.has_key?(:only) && opts.has_key?(:exclude) 
    215      
     242   
    216243      opts = shuffle_filters!(opts) 
    217        
     244     
    218245      case filter 
    219246      when Symbol, Proc, String 
    220         (self.after_filters ||= []) << [filter, opts] 
     247        if existing_filter = filters.find {|f| f.first.to_s[filter.to_s]} 
     248          existing_filter.last.replace(opts) 
     249        else 
     250          filters << [filter, opts] 
     251        end 
    221252      else 
    222253        raise(ArgumentError,  
    223           'After filters need to be either a Symbol, String or a Proc' 
     254          'Filters need to be either a Symbol, String or a Proc' 
    224255        )         
    225256      end 
    226257    end 
    227258     
     259    def self.skip_filter(filters, filter) 
     260      raise(ArgumentError,  
     261        'You can only skip filters that have a String or Symbol name.' 
     262      ) unless [Symbol, String].include? filter.class 
     263 
     264      MERB_LOGGER.warn("Filter #{filter} was not found in your filter chain." 
     265      ) unless filters.reject! {|f| f.first.to_s[filter.to_s] } 
     266    end 
     267 
     268    # Ensures that the passed in hash values are always arrays. 
     269    # 
     270    #   shuffle_filters!(:only => :new) #=> {:only => [:new]}    
     271 
    228272    def self.shuffle_filters!(opts={}) 
    229273      if opts[:only] && opts[:only].is_a?(Symbol) 
     
    236280    end 
    237281     
    238     def self.default_thrown_content 
    239       Hash.new{ |hash, key| hash[key] = "" } 
    240     end 
    241      
    242     # Set here to respond when rendering to cover the provides syntax of setting the content_type 
    243     def content_type_set? 
    244       false 
    245     end 
    246      
    247  
    248     def content_type 
    249       params[:format] || :html 
    250     end 
    251282  end   
    252283   
  • trunk/lib/merb/request.rb

    r1050 r1051  
    2323          request_method 
    2424        when :post 
    25           m = body_and_query_params['_method']  
     25          if self.class.parse_multipart_params 
     26            m = body_and_query_params.merge(multipart_params)['_method'] 
     27          else   
     28            m = body_and_query_params['_method'] 
     29          end   
    2630          m.downcase! if m 
    2731          METHODS.include?(m) ? m.to_sym : :post 
     
    6670        h = query_params 
    6771        h.merge!(body_params) if body_params 
    68         h 
     72        h.to_mash 
    6973      end 
    7074    end 
     
    7478        begin 
    7579          if Merb::Const::MULTIPART_REGEXP =~ content_type 
    76             self.class.parse_multipart(@body, $1, content_length) unless @body.size <= 0 
     80            if  @body.size <= 0 
     81              {} 
     82            else   
     83              self.class.parse_multipart(@body, $1, content_length) 
     84            end 
    7785          end 
    7886        rescue ControllerExceptions::MultiPartParseError => e 
     
    102110    def params 
    103111      @params ||= begin 
    104         h = body_and_query_params.to_mash.merge(route_params)       
     112        h = body_and_query_params.merge(route_params)       
    105113        h.merge!(multipart_params) if self.class.parse_multipart_params && multipart_params 
    106114        h.merge!(json_params) if self.class.parse_json_params && json_params 
  • trunk/spec/merb/controller_filters_spec.rb

    r739 r1051  
    55  before :filter1 
    66  before :will_halt, :only => :four 
     7   
     8  before :overwrite_before_filter, :only => :two 
     9  after  :overwrite_after_filter, :exclude => :four 
     10   
     11  after  :after_will_be_skipped 
     12  before :before_will_be_skipped 
     13 
    714  before Proc.new {|c| c.one }, :exclude => [:one, :three, :uses_params] 
    815  after  Proc.new {|c| c.five }, :exclude => [:one, :three, :uses_params]   
    916  after  :filter2 
    1017  before :modifies_param, :only => :uses_params 
    11   after :restores_param, :only => :uses_params 
    12    
     18  after  :restores_param, :only => :uses_params 
     19 
     20  before :overwrite_before_filter, :only => :three 
     21  after  :overwrite_after_filter, :exclude => [:one, :two, :uses_param] 
     22 
     23  skip_before :before_will_be_skipped 
     24  skip_after  :after_will_be_skipped 
     25   
     26  # filters 
    1327   
    1428  def will_halt 
     
    3852    @filter2='called' 
    3953  end 
    40      
     54   
     55  def before_will_be_skipped 
     56    @before_skip='called' 
     57  end 
     58   
     59  def after_will_be_skipped 
     60    @after_skip='called' 
     61  end 
     62   
     63  def overwrite_before_filter 
     64    @overwrite_before_filter='called' 
     65  end 
     66   
     67  def overwrite_after_filter 
     68    @overwrite_after_filter='called'     
     69  end 
     70   
     71  # actions 
     72   
    4173  def one 
    4274    session.data.should == {} 
     
    90122  end 
    91123   
    92 end   
     124end 
     125 
    93126describe "Dispatch and before/after filters" do 
    94127   
     
    185218    end 
    186219  end 
    187  
    188 end 
     220   
     221  it "should be overwritten by a subsequent call with the same filter" do 
     222    c = new_controller( 'two', TestFiltersController ) 
     223    c.dispatch(:two) 
     224    c.body.should == 'two' 
     225    c.instance_variable_get('@overwrite_before_filter').should == nil 
     226    c.instance_variable_get('@overwrite_after_filter').should == nil     
     227     
     228    c = new_controller( 'three', TestFiltersController ) 
     229    c.dispatch(:three) 
     230    c.body.should == 'three' 
     231    c.instance_variable_get('@overwrite_before_filter').should == 'called' 
     232    c.instance_variable_get('@overwrite_after_filter').should == 'called' 
     233  end 
     234   
     235  it "should not run if skipped" do 
     236    c = new_controller( 'one', TestFiltersController ) 
     237    c.dispatch(:one) 
     238    c.body.should == 'one' 
     239    c.instance_variable_get('@one').should == 'one'  
     240    c.instance_variable_get('@two').should == nil 
     241    c.instance_variable_get('@three').should == nil  
     242 
     243    c.instance_variable_get('@before_skip').should == nil 
     244    c.instance_variable_get('@after_skip').should == nil     
     245  end 
     246   
     247  it "should not allow skipping a filter that is not a symbol or string" do 
     248    ["before", "after"].each do |filter_type|     
     249      lambda { TestFiltersController.send('skip_'+filter_type, Proc.new{|c|puts c}) }.should raise_error(ArgumentError) 
     250    end 
     251  end 
     252 
     253end