Reputation: 1749
Is it possible to have a constraint on the optional route parameter that is 'in the middle' of the route?
I would like to have a following route:
get ':city(/:suburb)/:venue_type', venue_type: /bar|restaurant|cafe/
That would show a list of venues of specific type located in the city, or optionally have it narrowed down to suburb. The only :venue_types
that I support are bar, restaurant
and cafe
.
Now I would like to achieve following mappings:
/nyc/manhattan/bar -> :city = nyc, :suburb = manhattan, :venue_type = bar
/nyc/bar -> :city = nyc, :suburb = (nil), :venue_type = bar
/nyc/whatever/cafe -> :city = nyc, :suburb = whatever, :venue_type = cafe
/nyc/whatever -> :city = nyc, :suburb = whatever, :venue_type = (nil) - routing error
So far I've tried with the following which doesn't do the job:
class ValidSuburb
INVALID = %w[bar restaurant cafe]
def self.matches?(request)
request.params.has_key?(:suburb) && !INVALID.include?(request.params[:suburb])
end
end
get ':city(/:suburb)/:venue_type', venue_type: /bar|restaurant|cafe/, suburb: ValidSuburb.new
Is this possible to be achieved at all through constraints or do I have to resort in having multiple routes?
Upvotes: 0
Views: 1339
Reputation: 35370
Maybe I'm missing something, but wouldn't it be simpler to just have 2 routes?
get ':city/:venue_type', constraints: { venue_type: /bar|restaurant|cafe/ }
get ':city/:suburb/:venue_type', constraints: { venue_type: /bar|restaurant|cafe/ }
Here if anything but "bar"
, "restaurant"
, or "cafe"
are passed as that fragment after /nyc/.../bar
, the first route will be skipped, allowing it to match to the second route.
If /nyc/whatever
is passed, it won't meet the constraints/format of either route, causing the RouteError you're after.
Upvotes: 1