Skip to content

Commit 90d2802

Browse files
committed
Add support for other types of routing constraints
This now allows the use of arrays like this: get '/foo/:action', to: 'foo', constraints: { subdomain: %w[www admin] } or constraints where the request method returns an Fixnum like this: get '/foo', to: 'foo#index', constraints: { port: 8080 } Note that this only applies to constraints on the request - path constraints still need to be specified as Regexps as the various constraints are compiled into a single Regexp.
1 parent b28fc68 commit 90d2802

File tree

5 files changed

+237
-113
lines changed

5 files changed

+237
-113
lines changed

actionpack/CHANGELOG.md

+15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
## Rails 4.0.0 (unreleased) ##
22

3+
* Add support for routing constraints other than Regexp and String.
4+
For example this now allows the use of arrays like this:
5+
6+
get '/foo/:action', to: 'foo', constraints: { subdomain: %w[www admin] }
7+
8+
or constraints where the request method returns an Fixnum like this:
9+
10+
get '/foo', to: 'foo#index', constraints: { port: 8080 }
11+
12+
Note that this only applies to constraints on the request - path constraints
13+
still need to be specified as Regexps as the various constraints are compiled
14+
into a single Regexp.
15+
16+
*Andrew White*
17+
318
* Fix a bug in integration tests where setting the port via a url passed to
419
the process method was ignored when constructing the request environment.
520

actionpack/lib/action_dispatch/journey/route.rb

+24-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module ActionDispatch
22
module Journey # :nodoc:
33
class Route # :nodoc:
4-
attr_reader :app, :path, :verb, :defaults, :ip, :name
4+
attr_reader :app, :path, :defaults, :name
55

66
attr_reader :constraints
77
alias :conditions :constraints
@@ -12,15 +12,11 @@ class Route # :nodoc:
1212
# +path+ is a path constraint.
1313
# +constraints+ is a hash of constraints to be applied to this route.
1414
def initialize(name, app, path, constraints, defaults = {})
15-
constraints = constraints.dup
1615
@name = name
1716
@app = app
1817
@path = path
19-
@verb = constraints[:request_method] || //
20-
@ip = constraints.delete(:ip) || //
2118

2219
@constraints = constraints
23-
@constraints.keep_if { |_,v| Regexp === v || String === v }
2420
@defaults = defaults
2521
@required_defaults = nil
2622
@required_parts = nil
@@ -89,6 +85,29 @@ def required_defaults
8985
@defaults.dup.delete_if { |k,_| matches.include?(k) }
9086
end
9187
end
88+
89+
def matches?(request)
90+
constraints.all? do |method, value|
91+
next true unless request.respond_to?(method)
92+
93+
case value
94+
when Regexp, String
95+
value === request.send(method).to_s
96+
when Array
97+
value.include?(request.send(method))
98+
else
99+
value === request.send(method)
100+
end
101+
end
102+
end
103+
104+
def ip
105+
constraints[:ip] || //
106+
end
107+
108+
def verb
109+
constraints[:request_method] || //
110+
end
92111
end
93112
end
94113
end

actionpack/lib/action_dispatch/journey/router.rb

+1-5
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,7 @@ def find_routes env
131131
}
132132
routes.concat get_routes_as_head(routes)
133133

134-
routes.sort_by!(&:precedence).select! { |r|
135-
r.constraints.all? { |k, v| v === req.send(k) } &&
136-
r.verb === req.request_method
137-
}
138-
routes.reject! { |r| req.ip && !(r.ip === req.ip) }
134+
routes.sort_by!(&:precedence).select! { |r| r.matches?(req) }
139135

140136
routes.map! { |r|
141137
match_data = r.path.match(req.path_info)

0 commit comments

Comments
 (0)