How to make RESTful namespaced controllers

I looked all over for a way to use RESTful Rail with module namespaced controllers but everything that I read said that I wasn't possible. I figured out a way to do it so I thought that I would post it here for people like me who are looking. First, though, I want to give my thoughts about when would be a good time to use namespaces.

I am really interested in what Scott Raymond said about refactoring to rest:

"A big part of that redundancy was in having an Admin module, which quickly proved unnecessary. Instead, I just use before_filters to protect certain actions."

"I had gotten into the habit of unthinkingly creating an admin module at the start of every new Rails project, and I now think it's unnecessary much of the time."

http://scottraymond.net/2006/7/20/refactoring-to-rest

I think that one of the best things about the REST movement is that it encourages us to think about what we are doing and how we model things rather than just doing what we have always been doing. In most cases I think that namespaces are unnecessary and we would be better served by using things like before_filters.

However, in the application I am working on, I have several different types of users that all have access to the same resources, but they have different displays and most importantly different workflows. I could do it all in one giant controller with a lot of conditionals to cater to the different workflows, this is where I think namespaces make the most sense.

I am interested if anyone has any other solutions to handling this type of situation. I know that module namespaced controllers have minor problems like interference between controllers and modules with the same name, but I am not really interested in the problems. I am interested in other solutions.

Now, how to make RESTful module namespaced controllers:

Rails has built-in functionality to handle resource name conflicts that we can use to deal with controller namespaces.

If we have a model name Person and two controllers that operate on this resource name PeopleController and Admin::PeopleController, we can write the following routes in the routes.rb file:

map.resources :people map.resources :people, :path_prefix => 'admin', :controller => 'admin/people', :name_prefix => 'admin_'

This will create two sets of named routes, one for each controller. We just have to make sure that we use the right named route in the right place:

admin_person_url(@person)

or

person_url(@person)

I tested this using the crud 2 generator and it worked great. You just have to make sure that you replace all of the named routes that it creates by default. It would be nice if the generator actually supported namespaces, though. Maybe I will change it to do that one of these days.

-Jake