views:

109

answers:

1

I have a Rails 3 engine gem that is for basic user authentication and authorization. Within that Gem the config/routes.rb defines the following

resources :users
match '/:controller(/:action(/:id))'

When I do a rake routes from the application that requires this gem I get the following routes

rake routes|grep users
users GET   /users(.:format)               {:controller=>"users", :action=>"index"}
users POST  /users(.:format)               {:controller=>"users", :action=>"create"}
new_user GET  /users/new(.:format)         {:controller=>"users", :action=>"new"}
edit_user GET  /users/:id/edit(.:format)   {:controller=>"users", :action=>"edit"}
user GET   /users/:id(.:format)            {:controller=>"users", :action=>"show"}
user PUT   /users/:id(.:format)            {:controller=>"users", :action=>"update"}
user DELETE /users/:id(.:format)           {:controller=>"users", :action=>"destroy"}

This is what I expect.

However when I try to access the following routes via a browser

/users/137
/users/137/edit

I get the following error in the logs

AbstractController::ActionNotFound (The action '137' could not be found for UsersController):
  actionpack (3.0.0) lib/abstract_controller/base.rb:114:in `process'
  actionpack (3.0.0) lib/abstract_controller/rendering.rb:40:in `process'
  ...

What is interesting is that the following paths do work

/users/show/137
/users/edit/137

Also if I add the following to the routes.rb file in the application that is requiring the gem it all works as expected.

resources :users

Is there something I am missing or is this a bug?

Note that I am also doing the following when I start my application on the command line when I start the rails I set the following env variable

RAILS_RELATIVE_URL_ROOT="/my_app"

and in config.ru

map '/my_app' do
  run MSEL::Application
end
A: 

I experienced the same thing with a gem that I was creating. The engine routes are loaded after the application routes and I think this may be your problem. Take a look at rake routes without grepping for user. I suspect that you have a route in your application that takes precedence over the user routes. If you have match '/:controller(/:action(/:id))' in your application routes, then this will take precedence over the gem user route. Might explain why /users/show/137 works and not the RESTful routes. It may be possible to load your routes in the engine initializer to take precedence over the application routes. Post your full rake routes results and that may help us find a solution.

cowboycoded
Thanks cowboycoded. There is indeed the match you mentioned above. But assuming that I have that match in both routes.rb files (Gem and App) then if I change the loading order I will break routes in my app instead of my Gem routes being broken.
Will
if all your application routes are resources, this is not a problem. notice how the default routes.rb has this commented out.. match '/:controller(/:action(/:id))'. I think the rails team is trying to get people to move away from using this convention. But many people are probably still using it, so if you are distributing the gem it could be problem for your users. Its kind of a tricky thing to make work. There is some discussion here: https://rails.lighthouseapp.com/projects/8994/tickets/2592-plugin-routes-override-application-routes
cowboycoded
for my gem, I have the resource in the gem routes.rb and when my app uses a route that will take precendence, I just add the gem resource to my app route, like you mentioned in your question. Not an ideal solution, but it may be better than trying to hack and monkey patch to make everything work in the gem out of the box. Hopefullly this will be addressed in an upcoming version of rails
cowboycoded