aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/routing
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller/routing')
-rw-r--r--actionpack/lib/action_controller/routing/builder.rb53
-rw-r--r--actionpack/lib/action_controller/routing/route.rb2
-rw-r--r--actionpack/lib/action_controller/routing/routing_ext.rb4
-rw-r--r--actionpack/lib/action_controller/routing/segments.rb28
4 files changed, 53 insertions, 34 deletions
diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb
index 7b888fa8d2..d4e501e780 100644
--- a/actionpack/lib/action_controller/routing/builder.rb
+++ b/actionpack/lib/action_controller/routing/builder.rb
@@ -1,23 +1,16 @@
module ActionController
module Routing
class RouteBuilder #:nodoc:
- attr_accessor :separators, :optional_separators
+ attr_reader :separators, :optional_separators
+ attr_reader :separator_regexp, :nonseparator_regexp, :interval_regexp
def initialize
- self.separators = Routing::SEPARATORS
- self.optional_separators = %w( / )
- end
-
- def separator_pattern(inverted = false)
- "[#{'^' if inverted}#{Regexp.escape(separators.join)}]"
- end
-
- def interval_regexp
- Regexp.new "(.*?)(#{separators.source}|$)"
- end
+ @separators = Routing::SEPARATORS
+ @optional_separators = %w( / )
- def multiline_regexp?(expression)
- expression.options & Regexp::MULTILINE == Regexp::MULTILINE
+ @separator_regexp = /[#{Regexp.escape(separators.join)}]/
+ @nonseparator_regexp = /\A([^#{Regexp.escape(separators.join)}]+)/
+ @interval_regexp = /(.*?)(#{separator_regexp}|$)/
end
# Accepts a "route path" (a string defining a route), and returns the array
@@ -30,7 +23,7 @@ module ActionController
rest, segments = path, []
until rest.empty?
- segment, rest = segment_for rest
+ segment, rest = segment_for(rest)
segments << segment
end
segments
@@ -39,20 +32,20 @@ module ActionController
# A factory method that returns a new segment instance appropriate for the
# format of the given string.
def segment_for(string)
- segment = case string
- when /\A:(\w+)/
- key = $1.to_sym
- case key
- when :controller then ControllerSegment.new(key)
- else DynamicSegment.new key
- end
- when /\A\*(\w+)/ then PathSegment.new($1.to_sym, :optional => true)
- when /\A\?(.*?)\?/
- StaticSegment.new($1, :optional => true)
- when /\A(#{separator_pattern(:inverted)}+)/ then StaticSegment.new($1)
- when Regexp.new(separator_pattern) then
- DividerSegment.new($&, :optional => (optional_separators.include? $&))
- end
+ segment =
+ case string
+ when /\A:(\w+)/
+ key = $1.to_sym
+ key == :controller ? ControllerSegment.new(key) : DynamicSegment.new(key)
+ when /\A\*(\w+)/
+ PathSegment.new($1.to_sym, :optional => true)
+ when /\A\?(.*?)\?/
+ StaticSegment.new($1, :optional => true)
+ when nonseparator_regexp
+ StaticSegment.new($1)
+ when separator_regexp
+ DividerSegment.new($&, :optional => optional_separators.include?($&))
+ end
[segment, $~.post_match]
end
@@ -98,7 +91,7 @@ module ActionController
if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
end
- if multiline_regexp?(requirement)
+ if requirement.multiline?
raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
end
segment.regexp = requirement
diff --git a/actionpack/lib/action_controller/routing/route.rb b/actionpack/lib/action_controller/routing/route.rb
index 3b2cb28545..a610ec7e84 100644
--- a/actionpack/lib/action_controller/routing/route.rb
+++ b/actionpack/lib/action_controller/routing/route.rb
@@ -219,7 +219,7 @@ module ActionController
next_capture = 1
extraction = segments.collect do |segment|
x = segment.match_extraction(next_capture)
- next_capture += Regexp.new(segment.regexp_chunk).number_of_captures
+ next_capture += segment.number_of_captures
x
end
extraction.compact
diff --git a/actionpack/lib/action_controller/routing/routing_ext.rb b/actionpack/lib/action_controller/routing/routing_ext.rb
index 5f4ba90d0c..4a82b2af5f 100644
--- a/actionpack/lib/action_controller/routing/routing_ext.rb
+++ b/actionpack/lib/action_controller/routing/routing_ext.rb
@@ -27,6 +27,10 @@ class Regexp #:nodoc:
Regexp.new("|#{source}").match('').captures.length
end
+ def multiline?
+ options & MULTILINE == MULTILINE
+ end
+
class << self
def optionalize(pattern)
case unoptionalize(pattern)
diff --git a/actionpack/lib/action_controller/routing/segments.rb b/actionpack/lib/action_controller/routing/segments.rb
index e5f174ae2c..f6b03edcca 100644
--- a/actionpack/lib/action_controller/routing/segments.rb
+++ b/actionpack/lib/action_controller/routing/segments.rb
@@ -13,6 +13,10 @@ module ActionController
@is_optional = false
end
+ def number_of_captures
+ Regexp.new(regexp_chunk).number_of_captures
+ end
+
def extraction_code
nil
end
@@ -84,6 +88,10 @@ module ActionController
optional? ? Regexp.optionalize(chunk) : chunk
end
+ def number_of_captures
+ 0
+ end
+
def build_pattern(pattern)
escaped = Regexp.escape(value)
if optional? && ! pattern.empty?
@@ -194,10 +202,16 @@ module ActionController
end
end
+ def number_of_captures
+ if regexp
+ regexp.number_of_captures + 1
+ else
+ 1
+ end
+ end
+
def build_pattern(pattern)
- chunk = regexp_chunk
- chunk = "(#{chunk})" if Regexp.new(chunk).number_of_captures == 0
- pattern = "#{chunk}#{pattern}"
+ pattern = "#{regexp_chunk}#{pattern}"
optional? ? Regexp.optionalize(pattern) : pattern
end
@@ -230,6 +244,10 @@ module ActionController
"(?i-:(#{(regexp || Regexp.union(*possible_names)).source}))"
end
+ def number_of_captures
+ 1
+ end
+
# Don't URI.escape the controller name since it may contain slashes.
def interpolation_chunk(value_code = local_name)
"\#{#{value_code}.to_s}"
@@ -275,6 +293,10 @@ module ActionController
regexp || "(.*)"
end
+ def number_of_captures
+ regexp ? regexp.number_of_captures : 1
+ end
+
def optionality_implied?
true
end