One of the biggest features in the latest version of Rails is RESTful routes.
By writing the following in your routes.rb file (assuming you have a UsersController):
ActionController::Routing::Routes.draw do |map|
map.resources :users
end
You get the following named routes for free (excluding named routes that include a :format extension):
GET /users #index POST /users #create GET /users/new #new GET /users/1 #show PUT /users/1 #update GET /users/1;edit #edit DELETE /users/1 #destroy
The first column is the HTTP verb. Now Rails knows that browsers don’t support the HTTP verbs PUT and DELETE, so it fakes it by doing POSTs instead, and passing along a hidden field parameter named ‘_method’ whose value is either ‘put’ or ‘delete’.
So in order to support the basic CRUD actions in a controller, you need 4 unique routes. To me, the routes for #new and #edit are ugly. If we just had more HTTP verbs, we could eliminate both of those routes and reduce the total number of unique routes to 2 (actually, we could go all the way to just 1 route). Since Rails just uses POSTs and hidden parameters for PUT and DELETE, we can easily add our own HTTP verbs.
However, we can’t use #resources anymore in our routes.rb file though, instead we’ll have to create named routes for each of our 7 actions.
ActionController::Routing::Routes.draw do |map|
# Create
map.new_user 'users',
:conditions => { :method => :new },
:controller => 'users',
:action => 'new'
map.users 'users',
:conditions => { :method => :post },
:controller => 'users',
:action => 'create'
# Read
map.users 'users',
:conditions => { :method => :get },
:controller => 'users'
map.user 'users/:id',
:conditions => { :method => :get },
:controller => 'users',
:action => 'show'
# Update
map.edit_user 'users/:id',
:conditions => { :method => :edit },
:controller => 'users',
:action => 'edit'
map.user 'users/:id',
:conditions => { :method => :put },
:controller => 'users',
:action => 'update'
# Delete
map.user 'users/:id',
:conditions => { :method => :delete },
:controller => 'users',
:action => 'destroy'
end
The above code added 2 new HTTP verbs via the new :conditions parameter:
We can use the normal #link_to to create links to our #new and #edit actions by using the :method parameter:
link_to 'new', user_url(@user), :method => :new
link_to 'edit', user_url(@user), :method => :edit
This really is going to create a handler for this link’s onclick event that creates a form to the specified URL and POSTs to it with a hidden parameter value for ‘_method’ of either ‘new’ or ‘edit’ (i.e. this won’t degrade gracefully with javascript disabled, if you want that you’ll need to create forms that contain nothing but a button – unfortunately #button_to doesn’t support the :method parameter).