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

Changeset 9115

Show
Ignore:
Timestamp:
03/28/08 20:01:21 (2 years ago)
Author:
david
Message:

Added support for regexp flags like ignoring case in the :requirements part of routes declarations (closes #11421) [NeilW]

Files:

Legend:

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

    r9113 r9115  
    11*SVN* 
     2 
     3* Added support for regexp flags like ignoring case in the :requirements part of routes declarations #11421 [NeilW] 
    24 
    35* Fixed that ActionController::Base#read_multipart would fail if boundary was exactly 10240 bytes #10886 [ariejan] 
  • trunk/actionpack/lib/action_controller/routing.rb

    r9069 r9115  
    161161  #               :action => 'show', :requirements => { :postalcode => /\d{5}(-\d{4})?/ } 
    162162  # 
     163  # Formats can include the 'ignorecase' and 'extended syntax' regular 
     164  # expression modifiers: 
     165  # 
     166  #   map.geocode 'geocode/:postalcode', :controller => 'geocode', 
     167  #               :action => 'show', :postalcode => /hx\d\d\s\d[a-z]{2}/i 
     168  # 
     169  #   map.geocode 'geocode/:postalcode', :controller => 'geocode', 
     170  #               :action => 'show',:requirements => { 
     171  #                 :postalcode => /# Postcode format 
     172  #                                 \d{5} #Prefix 
     173  #                                 (-\d{4})? #Suffix 
     174  #                                 /x 
     175  #               } 
     176  # 
     177  # Using the multiline match modifier will raise an ArgumentError. 
     178  # Encoding regular expression modifiers are silently ignored. The 
     179  # match will always use the default encoding or ASCII. 
     180  # 
    163181  # == Route globbing 
    164182  # 
  • trunk/actionpack/lib/action_controller/routing/builder.rb

    r8652 r9115  
    1515      def interval_regexp 
    1616        Regexp.new "(.*?)(#{separators.source}|$)" 
     17      end 
     18 
     19      def multiline_regexp?(expression) 
     20        expression.options & Regexp::MULTILINE == Regexp::MULTILINE 
    1721      end 
    1822 
     
    99103            if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z} 
    100104              raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}" 
     105            end 
     106            if multiline_regexp?(requirement) 
     107              raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}" 
    101108            end 
    102109            segment.regexp = requirement 
  • trunk/actionpack/lib/action_controller/routing/route.rb

    r8652 r9115  
    6363        requirement_conditions = requirements.collect do |key, req| 
    6464          if req.is_a? Regexp 
    65             value_regexp = Regexp.new "\\A#{req.source}\\Z" 
     65            value_regexp = Regexp.new "\\A#{req.to_s}\\Z" 
    6666            "hash[:#{key}] && #{value_regexp.inspect} =~ options[:#{key}]" 
    6767          else 
  • trunk/actionpack/lib/action_controller/routing/segments.rb

    r8652 r9115  
    172172 
    173173      def value_regexp 
    174         Regexp.new "\\A#{regexp.source}\\Z" if regexp 
    175       end 
    176       def regexp_chunk 
    177         regexp ? "(#{regexp.source})" : "([^#{Routing::SEPARATORS.join}]+)" 
     174        Regexp.new "\\A#{regexp.to_s}\\Z" if regexp 
     175      end 
     176 
     177      def regexp_chunk 
     178        if regexp  
     179          if regexp_has_modifiers? 
     180            "(#{regexp.to_s})" 
     181          else 
     182            "(#{regexp.source})" 
     183          end 
     184        else 
     185          "([^#{Routing::SEPARATORS.join}]+)" 
     186        end 
    178187      end 
    179188 
     
    184193        optional? ? Regexp.optionalize(pattern) : pattern 
    185194      end 
     195 
    186196      def match_extraction(next_capture) 
    187197        # All non code-related keys (such as :id, :slug) are URI-unescaped as 
     
    202212      end 
    203213 
     214      def regexp_has_modifiers? 
     215        regexp.options & (Regexp::IGNORECASE | Regexp::EXTENDED) != 0 
     216      end 
     217 
    204218    end 
    205219 
  • trunk/actionpack/test/controller/routing_test.rb

    r9069 r9115  
    936936    a_segment.key = :action 
    937937    assert a_segment.optionality_implied? 
     938  end 
     939 
     940  def test_modifiers_must_be_handled_sensibly 
     941    a_segment = ROUTING::DynamicSegment.new 
     942    a_segment.regexp = /david|jamis/i 
     943    assert_equal "((?i-mx:david|jamis))stuff", a_segment.build_pattern('stuff') 
     944    a_segment.regexp = /david|jamis/x 
     945    assert_equal "((?x-mi:david|jamis))stuff", a_segment.build_pattern('stuff') 
     946    a_segment.regexp = /david|jamis/ 
     947    assert_equal "(david|jamis)stuff", a_segment.build_pattern('stuff') 
    938948  end 
    939949end 
     
    17241734    end 
    17251735  end 
    1726    
     1736 
    17271737  def test_non_path_route_requirements_match_all 
    17281738    set.draw do |map| 
     
    21112121    end 
    21122122  end 
     2123 
     2124  def test_route_requirements_with_unsupported_regexp_options_must_error 
     2125    assert_raises ArgumentError do 
     2126      set.draw do |map| 
     2127        map.connect 'page/:name', :controller => 'pages', 
     2128          :action => 'show', 
     2129          :requirements => {:name => /(david|jamis)/m} 
     2130      end 
     2131    end 
     2132  end 
     2133 
     2134  def test_route_requirements_with_supported_options_must_not_error 
     2135    assert_nothing_raised do 
     2136      set.draw do |map| 
     2137        map.connect 'page/:name', :controller => 'pages', 
     2138          :action => 'show', 
     2139          :requirements => {:name => /(david|jamis)/i} 
     2140      end 
     2141    end 
     2142    assert_nothing_raised do 
     2143      set.draw do |map| 
     2144        map.connect 'page/:name', :controller => 'pages', 
     2145          :action => 'show', 
     2146          :requirements => {:name => / # Desperately overcommented regexp 
     2147                                      ( #Either 
     2148                                       david #The Creator 
     2149                                      | #Or 
     2150                                        jamis #The Deployer 
     2151                                      )/x} 
     2152      end 
     2153    end 
     2154  end 
     2155 
     2156  def test_route_requirement_recognize_with_ignore_case 
     2157    set.draw do |map| 
     2158      map.connect 'page/:name', :controller => 'pages', 
     2159        :action => 'show', 
     2160        :requirements => {:name => /(david|jamis)/i} 
     2161    end 
     2162    assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis')) 
     2163    assert_raises ActionController::RoutingError do 
     2164      set.recognize_path('/page/davidjamis') 
     2165    end 
     2166    assert_equal({:controller => 'pages', :action => 'show', :name => 'DAVID'}, set.recognize_path('/page/DAVID')) 
     2167  end 
     2168 
     2169  def test_route_requirement_generate_with_ignore_case 
     2170    set.draw do |map| 
     2171      map.connect 'page/:name', :controller => 'pages', 
     2172        :action => 'show', 
     2173        :requirements => {:name => /(david|jamis)/i} 
     2174    end 
     2175    url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'}) 
     2176    assert_equal "/page/david", url 
     2177    assert_raises ActionController::RoutingError do 
     2178      url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'}) 
     2179    end 
     2180    url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) 
     2181    assert_equal "/page/JAMIS", url 
     2182  end 
     2183 
     2184  def test_route_requirement_recognize_with_extended_syntax 
     2185    set.draw do |map| 
     2186      map.connect 'page/:name', :controller => 'pages', 
     2187        :action => 'show', 
     2188        :requirements => {:name => / # Desperately overcommented regexp 
     2189                                    ( #Either 
     2190                                     david #The Creator 
     2191                                    | #Or 
     2192                                      jamis #The Deployer 
     2193                                    )/x} 
     2194    end 
     2195    assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis')) 
     2196    assert_equal({:controller => 'pages', :action => 'show', :name => 'david'}, set.recognize_path('/page/david')) 
     2197    assert_raises ActionController::RoutingError do 
     2198      set.recognize_path('/page/david #The Creator') 
     2199    end 
     2200    assert_raises ActionController::RoutingError do 
     2201      set.recognize_path('/page/David') 
     2202    end 
     2203  end 
     2204 
     2205  def test_route_requirement_generate_with_extended_syntax 
     2206    set.draw do |map| 
     2207      map.connect 'page/:name', :controller => 'pages', 
     2208        :action => 'show', 
     2209        :requirements => {:name => / # Desperately overcommented regexp 
     2210                                    ( #Either 
     2211                                     david #The Creator 
     2212                                    | #Or 
     2213                                      jamis #The Deployer 
     2214                                    )/x} 
     2215    end 
     2216    url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'}) 
     2217    assert_equal "/page/david", url 
     2218    assert_raises ActionController::RoutingError do 
     2219      url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'}) 
     2220    end 
     2221    assert_raises ActionController::RoutingError do 
     2222      url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) 
     2223    end 
     2224  end 
     2225 
     2226  def test_route_requirement_generate_with_xi_modifiers 
     2227    set.draw do |map| 
     2228      map.connect 'page/:name', :controller => 'pages', 
     2229        :action => 'show', 
     2230        :requirements => {:name => / # Desperately overcommented regexp 
     2231                                    ( #Either 
     2232                                     david #The Creator 
     2233                                    | #Or 
     2234                                      jamis #The Deployer 
     2235                                    )/xi} 
     2236    end 
     2237    url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'}) 
     2238    assert_equal "/page/JAMIS", url 
     2239  end 
     2240 
     2241  def test_route_requirement_recognize_with_xi_modifiers 
     2242    set.draw do |map| 
     2243      map.connect 'page/:name', :controller => 'pages', 
     2244        :action => 'show', 
     2245        :requirements => {:name => / # Desperately overcommented regexp 
     2246                                    ( #Either 
     2247                                     david #The Creator 
     2248                                    | #Or 
     2249                                      jamis #The Deployer 
     2250                                    )/xi} 
     2251    end 
     2252    assert_equal({:controller => 'pages', :action => 'show', :name => 'JAMIS'}, set.recognize_path('/page/JAMIS')) 
     2253  end 
     2254 
    21132255   
    21142256end 
     
    21912333    assert c.ancestors.include?(h) 
    21922334  end 
    2193    
     2335 
    21942336end 
    21952337