Perspectives

Scissors2

Many Web Applications these days consist of two main parts: the public facing front-end, and the private, secure administration area. When developing with Ruby on Rails, the convention is to try to write code as DRY (don't repeat yourself) as possible and use one single controller for both the public side and the administration side of the site. For certain circumstances this is fine, but I think there is some flexibility here, and recently I've noticed that many times the Admin logic is quite a bit different that the public facing functionality — enough so to warrant its own set of admin controllers and views.

With Rails 2.0+, you can use namespacing to keep the admin controller logic and views separate from the public controller logic and views. I've come to really like the way this helps to keep both sections of the site separate and organized.

I'll demonstrate a very simple example of a web app that provides a way for an Administrator to create, edit, and delete articles with one controller, and for a visitor to view those articles with a separate controller.

Create Your Controllers

After you've created your new rails app, we can proceed by generating our two controllers to access our articles:

# our private admin controller uses namespacing. Notice the Admin:: prefix
./script/generate controller Admin::Articles
# our public controller is created normally
./script/generate controller Articles

We now have two controllers named articles_controller.rb. The public controller lives in app/controllers/ and the private controller lives in app/controllers/admin/ with its respective views in app/views/admin/articles. Once you've created the necessary views, you should have a file structure similar to the image below. Our public controller only needs two methods at this point: 'index' and 'show', while our admin controller will require all 7 standard REST methods.

Create Your Routes

Before either of these controllers can function, we need to setup our routes in the config/routes.rb file.

map.namespace :admin do |admin|
  admin.resources :articles
end

map.resources :articles
  

Take a second and run rake routes on the command line to view all of your current routes. You'll notice you now have 2 sets of articles routes, one of which targets your admin controller, and one which targets your public controller.

Handling Links and Forms

So how does this change how links are handled in the views? It turns out it's not all that complicated thanks to Rails creating a set of admin specific URL generation methods:

# Create a link to the public article page '/articles/:id'
<%= link_to 'View Article', article_url(@article) %>

# Create a link to view the article in the Admin area '/admin/articles/:id'
<%= link_to 'View Article', admin_article_url(@article) %>

# Create a link to edit the article in the Admin area '/admin/articles/:id/edit'
<%= link_to 'Edit Article', edit_admin_article_url(@article) %>

The same goes for using forms in the Admin area. Instead of using <% form_for(@article) do |f| %> you simply add in the admin namespace, and voila, your forms submit to the /admin/articles controller:

# Create a form that submits to the /admin/articles controller
<% form_for([:admin, @article]) do |f| %>
....
<% end %>

Securing and Styling Your Admin Controllers

You will no doubt want to secure all of your Admin controllers and require an Admin user to be logged in. If you use a plugin like the popular RESTUL Authentication, you can simply apply the before_filter :login_required to the top of each Admin controller.

Most of the time the Administration area is also styled differently than the public facing area of the site. Here we can simply put something like layout 'admin' at the top of our Admin controllers to use a separate admin.html.erb layout file instead of the public application.html.erb layout file.

class Admin::ArticlesController < ApplicationController
  before_filter :login_required
  layout 'admin'
  
  ... REST methods here ...
end

Wrapping Things Up...

You should now have the beginnings of a web app with a set of self-contained, password-protected Admin CMS controllers prefixed with /admin, and a set publicly viewable front-end controllers. If you're feeling adventurous, you could even extract the controllers, views, routes, and stylesheets into a plugin or a generator if many of the CMS features will be used throughout a variety of different applications.




RSS Feed


CATEGORIES


ARCHIVES


BOOKMARKED


Add to Technorati Favorites