RESTful Routes Demystified

Sep 14, 2008

RESTful application design is a rails-standard way to structure your CRUD actions. It simplifies your controllers into 7 actions: index, show, new, create, edit, update, and destroy. Here are some basics for working with RESTful routes.

The simple way to get the default routes:

ActionController::Routing::Routes.draw do |map|
  map.resources :products

Route Options

Several options can be passed to the route to customize it. You can use the path_prefix option to customize the appearance of your URLs. The name_prefix option is used to change the way the routes are called. The controller option is used to specify a custom controller.

# start all of your URLs with /admin
# '/admin/projects/id/edit/index.html'
map.resources :products, :path_prefix => '/admin/index.html'

# start all of your routes with 'mng_'
# mng_products_path or mng_product_path(:id)
map.resources :products, :name_prefix => 'mng_'

# if you want your URLs to say '/products/id/index.html'
# but your controller is called 'store_products'
map.resources :products, :controller => 'store_products'

Adding Routes for Custom Actions

The resources method will generate the routes for the default REST actions, but what if you want to add your own actions to your controller? There are two options for adding custom routes: the member option is for routes that require an id to be passed, and the collection option is for actions that don't require an id. With each option, you must pass a hash with the action name and the HTTP method.

# return_policy_products_path => '/products/return_policy/index.html'
# submit_question_products_path => '/products/submit_question/index.html'
map.resources :products, :collection => {:return_policy => :get, :submit_question => :post}

# warranty_product_path(:id) => '/products/id/warranty/index.html'
map.resources :products, :member => {:warranty => :get}

Nested Routes

You can nest routes for objects that are related. Say the products have customer reviews with a has_many relationship. You can nest the resources call within the products route definition.

# product_reviews_path(:product_id) => '/products/product_id/reviews/index.html'
# product_review_path(:product_id, :id) => '/products/product_id/reviews/id/index.html'
# edit_product_review_path(:product_id, :id) => '/products/product_id/reviews/id/edit/index.html'
map.resources :products do |products|
  products.resources :reviews, :controller => 'customer_reviews'

Those are the basics, but there are a LOT more possibilities. If you're interested, there is a really great guide to all things routes.

Tagged: railsroutestutorial