Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3: making a catch-all route easier to read and amend

I'm trying to write a catch-all route in Rails 3, but I want to reserve some terms in it. I'm specifically following the example put forth in this post, in the answer by David Burrows: Dynamic routes with Rails 3

The syntax I am using is the following:

match '*path' => 'router#routing', :constraints => lambda{|req|  (req.env["REQUEST_PATH"] =~ /(users|my-stuff)/).nil? }

Now, that syntax works just fine - if a user visits a page with "user" or "my-stuff" in the path, it falls through the catch-all and goes to a specific place. If the user goes to any other URL, it goes to my routing logic.

My question is more about readability - is there a way I can match the route against something other than a regex? Is there a way to provide an array of terms to match against? Also, is there a way to match specific segments of the route, as opposed to the entire thing?

Obviously Rails has built-in routing, but this project has a requirement that for certain routes, the controller not be present in the URL. Hence, the catch-all.

Thanks for any help

Here's the updated routes file per the answer below:

class RouteConstraint
  RESERVED_ROUTES = ['users', 'my-stuff']

  def matches?(request)
    !RESERVED_ROUTES.map {|r| request.path.include?(r)}.empty?
  end
end

App::Application.routes.draw do
  resources :categories
  resources :sites

  match '*path' => 'router#routing', :constraints => RouteConstraint.new

  devise_for :users, :path_names =>{ :sign_in => 'login', :sign_out => 'logout', :registration => 'register' }
  root :to => "router#routing"
end
like image 873
Kevin Whitaker Avatar asked Oct 07 '11 13:10

Kevin Whitaker


1 Answers

You can use a class to specify the constraints if you want something cleaner once you have multiple routes to try:

class MyConstraint
  BYPASSED_ROUTES = ['users', 'my-stuff']

  def matches?(request)
    BYPASSED_ROUTES.map {|r| request.path.include?(r)} .empty?
  end
end

TwitterClone::Application.routes.draw do
  match "*path" => "router#routing", :constraints => MyConstraint.new
end

This example is adapted from the rails routing guide.

like image 59
Benoit Garret Avatar answered Oct 23 '22 11:10

Benoit Garret