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 R. 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

I guess it was all there in the documentation. Just hard to digest and
understand how it all comes together. Thank you so much for the
explanation, Jake! This is exactly what I was looking for. Answered all
of my questions! :slight_smile:

I have a problem with Rails 1.2.2:

  1. create a rails app.
  2. script/generate scaffold_resource Admin::User name:string
    (I has to create the layout/admin dir by hand and run the command
    once more)
  3. rake db:migrate (after creating the database of cource)
  4. map.resources :users, :path_prefix => ‘admin’, :controller
    =>‘admin/users’, :name_prefix => ‘admin_’
  5. script/console

Admin::User
=> Admin::User

Admin::User.find(:all)
ActiveRecord::StatementInvalid: Mysql::Error: #42S02Table
‘db_dev.users’ doesn’t exist: SELECT * users

So has anybody an idea why the table ‘admin_users’ was created
correctly,
but the table ‘users’ is accessed by Admin::User.find(:all)?

Thanks in advance,
Stefan

Or do I really have to specify the table name in the model to fix it:

class Admin::User < ActiveRecord::Base
set_table_name :admin_users
end

Cheers,
Stefan

Another problem:

After setting the table name at least something is workink, but:

'admin_user_path(user) is known, but ‘edit_admin_user_path(user)’ and
‘new_admin_user_path’ are unknown, instead ‘edit_user_path(user)’
and ‘new_user_path’ were created (but of cource not correctly working).

Is Rails 1.2.2 that buggy when it comes to using module namespace or
am I missing something in routes.rb or…???

What’s going on? Maybe nobody really cares about namespace in Rails!?
Creating a big enterprise application in Rails without having namespaces
doesn’t sounds like having fun, Ops…

Sorry, forget about my last mail, it’s not that bad! After dumping out
some routing info on the console:

GET /admin/users/
{:controller=>“admin/users”, :action=>“index”}
GET /admin/users.:format/
{:controller=>“admin/users”, :action=>“index”}
POST /admin/users/
{:controller=>“admin/users”, :action=>“create”}
POST /admin/users.:format/
{:controller=>“admin/users”, :action=>“create”}
GET /admin/users/new/
{:controller=>“admin/users”, :action=>“new”}
GET /admin/users/new.:format/
{:controller=>“admin/users”, :action=>“new”}
GET /admin/users/:id;edit/
{:controller=>“admin/users”, :action=>“edit”}
GET /admin/users/:id.:format;edit/
{:controller=>“admin/users”, :action=>“edit”}
GET /admin/users/:id/
{:controller=>“admin/users”, :action=>“show”}
GET /admin/users/:id.:format/
{:controller=>“admin/users”, :action=>“show”}
PUT /admin/users/:id/
{:controller=>“admin/users”, :action=>“update”}
PUT /admin/users/:id.:format/
{:controller=>“admin/users”, :action=>“update”}
DELETE /admin/users/:id/
{:controller=>“admin/users”, :action=>“destroy”}
DELETE /admin/users/:id.:format/
{:controller=>“admin/users”, :action=>“destroy”}
formatted_admin_edit_user: GET /admin/users/:id.:format;edit/
{:controller=>“admin/users”, :action=>“edit”}
admin_edit_user: GET /admin/users/:id;edit/
{:controller=>“admin/users”, :action=>“edit”}
formatted_admin_new_user: GET /admin/users/new.:format/
{:controller=>“admin/users”, :action=>“new”}
admin_new_user: GET /admin/users/new/
{:controller=>“admin/users”, :action=>“new”}
formatted_admin_users: GET /admin/users.:format/
{:controller=>“admin/users”, :action=>“index”}
admin_users: GET /admin/users/
{:controller=>“admin/users”, :action=>“index”}
formatted_admin_user: GET /admin/users/:id.:format/
{:controller=>“admin/users”, :action=>“show”}
admin_user: GET /admin/users/:id/
{:controller=>“admin/users”, :action=>“show”}

it was clear: My mistake, it should correctly be named:

admin_user_path(user)
admin_edit_user_path(user)
admin_new_user_path

Now so far it works, only the ‘set_table_name :admin_users’ still bother
me :wink:

So happy railing with namespaced controllers,
Stefan