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
$> 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:
$> 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.
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
- You can create named routes to satisfy the “/admin” requirement
- 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.