Learning Rails: Namespaced Controllers

A common requirement of a visitor facing web application is that the administration component of the app is behind a login with a different layout, style sheet and feel. Rails 2.0 makes this very simple with namespaced controllers. On a recent project the specs called for the administration to live under an /admin path, simple enough.

Creating the Admin Interface

1
$> script/generate controller admin/employees index show new create edit update

Perfect, now I’ve got my new controller and some views.


  /app/controllers/admin/employees_controller.rb
  /app/views/admin/employees/
    /app/views/admin/employees/index.html.erb
    /app/views/admin/employees/show.html.erb
    /app/views/admin/employees/new.html.erb
    /app/views/admin/employees/edit.html.erb

We’ll need to create a new layout and style sheet for our admin interface:

1
2
$> touch app/views/layouts/admin.html.erb
$> touch public/stylesheets/admin.css

A quick edit to our routes file and everything is in place:

1
2
3
map.namespace :admin do |admin|
  admin.resources :employees
end

In a few short steps we’ve got everything we need for our /admin area. Now we just have to build out all of the controller actions, write all of our tests, add the markup to the views… and then we have to do it all over again for the public facing controller.

The Drawbacks

At this point I realized how un-sexy this technique is. For each Model that I want to display to the public and edit in the admin I have to create two controllers, two views, two layouts, two style sheets and twice as many bugs, typos and frustrations. GAH. By the time you write all of the specs for each controller you’ve got some ridiculous code:test ratio and you never want to look at TextMate again.

The Expense of “Keepin’ it DRY

As a rails developer you should always think about “Keepin’ it DRRRYYYY” but sometimes the pursuit of DRY just isn’t worth it. As far as I can tell, keeping the admin and public controllers, views and tests separate and DRY adds way more complexity and confusion when you use namespaced controllers. I just don’t think it’s worth it

Alternatives

  1. You can create named routes to satisfy the “/admin” requirement
  2. Write an application controller method to determine which template to render (based on admin/public visitor status)

That’s it really, it doesn’t take much to keep things simple® and avoid a bunch of duplicate-in-concept code. The next time you reach for namespaced controllers to satisfy this type of functionality, think twice, it might save you a lot of trouble.

Comments

  1. says

    Well, it’s been a while since you wrote this, but I’m now facing exactly the same problem (‘Portin out a PHP CMS into Rails). Excepting I don’t understand you : “two controllers, two views, two stylesheets…” Well, isn’t that the way it MUST be ?! I mean, in a CMS, your back do have many features and views that your front does not handle, no ?! It appears to me total and “absolute” split of the two sides is necessary (and what about themes, for instance ?…)
    Your post surprised me, is there something I totally miss ?
    About the namespacing of the controllers, well, it is clearly not a solution without consequences, but in my opinion it is the only clean, powerful, and proper solution.

    … But as I always say : I maybe wrong ;-)

  2. says

    Couldn’t agree more with this article. I am deciding between a separate namespaced admin vs a pure roles based solution like declarative_authorization and certainly a namespaced approach sounds much better to me for two reasons. First, an admin’s workflow is not necessarily similar to how a normal user would use the application. So there’d be separate view and controllers those those workflows. Don’t think that counts as duplication. Secondly, management is easier. Everything under the namespace /admin has to be protected by all means. There is no need to worry about modifying views if user is this/that, etc.

    That said, I think a perfect solution would be to have both namespaced admin area for the application admins, and a role based approach for all other kinds of users.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>