aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/journey
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/journey')
-rw-r--r--actionpack/lib/action_dispatch/journey/nodes/node.rb4
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb65
2 files changed, 63 insertions, 6 deletions
diff --git a/actionpack/lib/action_dispatch/journey/nodes/node.rb b/actionpack/lib/action_dispatch/journey/nodes/node.rb
index 542e8c6577..d069bf0205 100644
--- a/actionpack/lib/action_dispatch/journey/nodes/node.rb
+++ b/actionpack/lib/action_dispatch/journey/nodes/node.rb
@@ -41,6 +41,7 @@ module ActionDispatch
def literal?; false; end
def terminal?; false; end
def star?; false; end
+ def cat?; false; end
end
class Terminal < Node # :nodoc:
@@ -72,11 +73,13 @@ module ActionDispatch
class Symbol < Terminal # :nodoc:
attr_accessor :regexp
alias :symbol :regexp
+ attr_reader :name
DEFAULT_EXP = /[^\.\/\?]+/
def initialize(left)
super
@regexp = DEFAULT_EXP
+ @name = left.tr '*:'.freeze, ''.freeze
end
def default_regexp?
@@ -115,6 +118,7 @@ module ActionDispatch
end
class Cat < Binary # :nodoc:
+ def cat?; true; end
def type; :CAT; end
end
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
index d44c3d31d7..209cd20d80 100644
--- a/actionpack/lib/action_dispatch/journey/route.rb
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -8,18 +8,61 @@ module ActionDispatch
attr_accessor :precedence
+ module VerbMatchers
+ VERBS = %w{ DELETE GET HEAD OPTIONS LINK PATCH POST PUT TRACE UNLINK }
+ VERBS.each do |v|
+ class_eval <<-eoc
+ class #{v}
+ def self.verb; name.split("::").last; end
+ def self.call(req); req.#{v.downcase}?; end
+ end
+ eoc
+ end
+
+ class Unknown
+ attr_reader :verb
+
+ def initialize(verb)
+ @verb = verb
+ end
+
+ def call(request); @verb === request.request_method; end
+ end
+
+ class All
+ def self.call(_); true; end
+ def self.verb; ''; end
+ end
+
+ VERB_TO_CLASS = VERBS.each_with_object({ :all => All }) do |verb, hash|
+ klass = const_get verb
+ hash[verb] = klass
+ hash[verb.downcase] = klass
+ hash[verb.downcase.to_sym] = klass
+ end
+
+ end
+
+ def self.verb_matcher(verb)
+ VerbMatchers::VERB_TO_CLASS.fetch(verb) do
+ VerbMatchers::Unknown.new verb.to_s.dasherize.upcase
+ end
+ end
+
def self.build(name, app, path, constraints, required_defaults, defaults)
- new name, app, path, constraints, required_defaults, defaults
+ request_method_match = verb_matcher(constraints.delete(:request_method))
+ new name, app, path, constraints, required_defaults, defaults, request_method_match
end
##
# +path+ is a path constraint.
# +constraints+ is a hash of constraints to be applied to this route.
- def initialize(name, app, path, constraints, required_defaults, defaults)
+ def initialize(name, app, path, constraints, required_defaults, defaults, request_method_match)
@name = name
@app = app
@path = path
+ @request_method_match = request_method_match
@constraints = constraints
@defaults = defaults
@required_defaults = nil
@@ -96,7 +139,8 @@ module ActionDispatch
end
def matches?(request)
- constraints.all? do |method, value|
+ match_verb(request) &&
+ constraints.all? { |method, value|
case value
when Regexp, String
value === request.send(method).to_s
@@ -109,7 +153,7 @@ module ActionDispatch
else
value === request.send(method)
end
- end
+ }
end
def ip
@@ -117,11 +161,20 @@ module ActionDispatch
end
def requires_matching_verb?
- constraints[:request_method]
+ !@request_method_match.all? { |x| x == VerbMatchers::All }
end
def verb
- constraints[:request_method] || //
+ %r[^#{verbs.join('|')}$]
+ end
+
+ private
+ def verbs
+ @request_method_match.map(&:verb)
+ end
+
+ def match_verb(request)
+ @request_method_match.any? { |m| m.call request }
end
end
end