Skip to content
This repository
Browse code

Escape globbed parameters in routes correctly.

:controller => 'glob', :action=> 'show', :additional => ['foo/bar', 'baz']

Should generate /glob/show/foo%2Fbar/baz not  /glob/show/foo/bar/baz
  • Loading branch information...
commit 6776edccf6fb553eb0ac6db55e1d30df1b5b6589 1 parent dc4eec1
authored May 10, 2008 NZKoz committed May 10, 2008
9  actionpack/lib/action_controller/routing/segments.rb
@@ -244,11 +244,12 @@ def match_extraction(next_capture)
244 244
     end
245 245
 
246 246
     class PathSegment < DynamicSegment #:nodoc:
247  
-      RESERVED_PCHAR = "#{Segment::RESERVED_PCHAR}/"
248  
-      UNSAFE_PCHAR = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}]", false, 'N').freeze
249  
-
250 247
       def interpolation_chunk(value_code = "#{local_name}")
251  
-        "\#{URI.escape(#{value_code}.to_s, ActionController::Routing::PathSegment::UNSAFE_PCHAR)}"
  248
+        "\#{#{value_code}}"
  249
+      end
  250
+
  251
+      def extract_value
  252
+        "#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| URI.escape(path_component, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
252 253
       end
253 254
 
254 255
       def default
12  actionpack/test/controller/routing_test.rb
@@ -25,7 +25,7 @@ def setup
25 25
     ActionController::Routing.use_controllers! ['controller']
26 26
     @set = ActionController::Routing::RouteSet.new
27 27
     @set.draw do |map|
28  
-      map.connect ':controller/:action/:variable'
  28
+      map.connect ':controller/:action/:variable/*additional'
29 29
     end
30 30
 
31 31
     safe, unsafe = %w(: @ & = + $ , ;), %w(^ / ? # [ ])
@@ -36,17 +36,19 @@ def setup
36 36
   end
37 37
 
38 38
   def test_route_generation_escapes_unsafe_path_characters
39  
-    assert_equal "/contr#{@segment}oller/act#{@escaped}ion/var#{@escaped}iable",
  39
+    assert_equal "/contr#{@segment}oller/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2",
40 40
       @set.generate(:controller => "contr#{@segment}oller",
41 41
                     :action => "act#{@segment}ion",
42  
-                    :variable => "var#{@segment}iable")
  42
+                    :variable => "var#{@segment}iable",
  43
+                    :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"])
43 44
   end
44 45
 
45 46
   def test_route_recognition_unescapes_path_components
46 47
     options = { :controller => "controller",
47 48
                 :action => "act#{@segment}ion",
48  
-                :variable => "var#{@segment}iable" }
49  
-    assert_equal options, @set.recognize_path("/controller/act#{@escaped}ion/var#{@escaped}iable")
  49
+                :variable => "var#{@segment}iable",
  50
+                :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"] }
  51
+    assert_equal options, @set.recognize_path("/controller/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2")
50 52
   end
51 53
 end
52 54
 

1 note on commit 6776edc

Dima Sabanin

Now if I pass url_for(:something => my_obj), my_obj is not called to_param, so I get undefined method .collect error. Is that intentional?

Please sign in to comment.
Something went wrong with that request. Please try again.