Skip to content
Permalink
Browse files
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.
  • Loading branch information
pixeltrix committed Jan 15, 2013
1 parent b28fc68 commit 90d2802
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 113 deletions.
@@ -1,5 +1,20 @@
## Rails 4.0.0 (unreleased) ##

* Add support for routing constraints other than Regexp and String.
For example 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.

*Andrew White*

* Fix a bug in integration tests where setting the port via a url passed to
the process method was ignored when constructing the request environment.

@@ -1,7 +1,7 @@
module ActionDispatch
module Journey # :nodoc:
class Route # :nodoc:
attr_reader :app, :path, :verb, :defaults, :ip, :name
attr_reader :app, :path, :defaults, :name

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

@constraints = constraints
@constraints.keep_if { |_,v| Regexp === v || String === v }
@defaults = defaults
@required_defaults = nil
@required_parts = nil
@@ -89,6 +85,29 @@ def required_defaults
@defaults.dup.delete_if { |k,_| matches.include?(k) }
end
end

def matches?(request)
constraints.all? do |method, value|
next true unless request.respond_to?(method)

case value
when Regexp, String
value === request.send(method).to_s
when Array
value.include?(request.send(method))
else
value === request.send(method)
end
end
end

def ip
constraints[:ip] || //
end

def verb
constraints[:request_method] || //
end
end
end
end
@@ -131,11 +131,7 @@ def find_routes env
}
routes.concat get_routes_as_head(routes)

routes.sort_by!(&:precedence).select! { |r|
r.constraints.all? { |k, v| v === req.send(k) } &&
r.verb === req.request_method
}
routes.reject! { |r| req.ip && !(r.ip === req.ip) }
routes.sort_by!(&:precedence).select! { |r| r.matches?(req) }

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

0 comments on commit 90d2802

Please sign in to comment.