Wednesday, September 17, 2008

Rails: RESTful namespaces shall set you free

Being one of the its admirers, I try to conform to REST almost all the time, thanks to Rails support. One of the problems in following the REST model is the problem of resource naming. In its simplest forms, REST is about mapping each resource to a unique name with a set of conventional urls. The problem appears in a case when you need more than one representation to some/all of your application resources (in the same format), or in other words, if some resources need to have colliding names.

A famous example of such a case is application with administration modules. Regularly, most of the resources are needed to be duplicated in another representation for the admin. For example, you already have a resource named 'Item' and you need another one with the same name and different representation for the admin.

Rails solves this problem with a handy feature: RESTful namespaces. RESTful routes could be managed in different namespaces to avoid names collision. What's elegant about it is that when you nest a resource in a namespace, it's mapped directly to an expected controller class that's a member in a module whose name is the same as the namespace. Also, the namespace contributes to the url helpers just as nested resources.

For example, while the configuration:
map.resources :items

maps to ItemsController and generates a set of helpers/routes like:

items_path() => /items
item_path(id) => /items/id
new_item_path() => /items/new
edit_item_path(id) => /items/id/edit

, The configuration:

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

maps to Admin::ItemsController and generates a set of helpers/routes like:

admin_items_path() => /admin/items
admin_item_path(id) => /admin/items/id
new_admin_item_path() => /admin/items/new
edit_admin_item_path(id) => /admin/items/id/edit


So, essentially what happens is a total collision removal(resource names, controller names, helpers, urls) with a minimal effort. I gotta admit, I love Ruby in Rails.


1 comment:

Anonymous said...

I've read ~500 pages to try and find a decent way to handle this type of duality for some controllers, you just saved my day!