Skip to content

Instantly share code, notes, and snippets.

@tenderlove
Created March 15, 2011 23:03
Show Gist options
  • Save tenderlove/871699 to your computer and use it in GitHub Desktop.
Save tenderlove/871699 to your computer and use it in GitHub Desktop.
Routing Quiz

Rails Quiz

Leave your answer in the comments!

Given this routes file:

Omg::Application.routes.draw do
  match ':controller(/:action(/:id(.:format)))'
end

And these controllers:

module Admin
  class UserController < ActionController::Base
    def show
    end
  end
end

class AdminController < ActionController::Base
  def show
  end
end

class Products < ActionController::Base
  def show
  end
end

What controller do these urls route to?

/products/show/10

/products/show

/admin/user/show/10

/admin/user/show
@eggie5
Copy link

eggie5 commented Mar 15, 2011

/products/show/10 => products controller

/products/show => products controller

/admin/user/show/10 => admin controller

/admin/user/sho => admin controller

@buddhamagnet
Copy link

  1. products controller, show action, id 10
  2. products controller, show action
  3. admin module, user controller, show action, id 10
  4. admin module, user controller, show action

@tenderlove
Copy link
Author

I've posted the answer here.

@stevenharman
Copy link

this certainly breaks the Element of Least Surprise. The products routes make perfect sense, as does /admin/user/show #=> AdminController#user(show).

That 3rd route has me stumped; I would expect no route to match. I suppose I could crack the router code to have a look at WTF is going on, but having to do so is kinda stinky.

@oriolgual
Copy link

Isn't the AdminController missing the user action? (Like here: https://github.com/tenderlove/lolwut/blob/master/app/controllers/admin_controller.rb)

@pixeltrix
Copy link

It's my fault: rails/rails@b802a0d

However, without that commit it would break backward compatibility for namespaced controllers. The regexp constraint is non-greedy by default, otherwise it would swallow all of the path as the controller name. This is because the other segments are optional and this causes the strange result for 4. I added a note about dynamic controller segments in the routing guide: http://guides.rubyonrails.org/routing.html#dynamic-segments.

Adding two routes, one with a custom regexp constraint should give more reasonable results:

match ':controller(/:action(/:id(.:format)))', :controller => /admin\/[^\/]+/
match ':controller(/:action(/:id(.:format)))'

@oriolgual The thing to remember is that Rack::Mount is doing the route recognition and it has no knowledge of controllers, actions, etc and it doesn't look at what is in the app folder. To Rack::Mount :controller is no different than an other dynamic segment like :id, :user_id, etc. All it does is match patterns - once that pattern is matched it's handed back to ActionDispatch to call the appropriate controller/action.

@oriolgual
Copy link

Thanks for the explanation @pixeltrix!

@joseph-ravenwolfe
Copy link

Shouldn't it be ProductsController < ActionController::Base instead of Products?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment