About Me

My photo
PhD Candidate at Purdue University, Computer Science.

Thursday, March 29, 2007

Practical RESTful rails Example

Using PUT and DELETE with GET and POST is the main idea behind REST to simulate the CRUD mappings.
Note: Web-Browsers neither support PUT nor DELETE

Create a Rails project and the Resource Scaffolding
$ rails warehouse
warehouse> ruby script/generate scaffold_resource product name:string desc:text
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/products
exists test/functional/
exists test/unit/
create app/views/products/index.rhtml
create app/views/products/show.rhtml
create app/views/products/new.rhtml
create app/views/products/edit.rhtml
create app/views/layouts/products.rhtml
create public/stylesheets/scaffold.css
create app/models/product.rb
create app/controllers/products_controller.rb
create test/functional/products_controller_test.rb
create app/helpers/products_helper.rb
create test/unit/product_test.rb
create test/fixtures/products.yml
create db/migrate
create db/migrate/001_create_products.rb
route map.resources :products
warehouse> rake db:migrate
== CreateProducts: migrating ==================================================
-- create_table(:products, {:options=>"default charset=UTF8"})
-> 0.0160s
== CreateProducts: migrated (0.0160s) =========================================
We can now have a look to the generated controller.

An example of URL in REST is (/product/1) instead of (/products/show/1). We notice that the action is dropped from the URL, we can't know what is the action that should happen to the addressed resource.
The REST actions are activated through a combination of resource-url and HTTP verb. Another feature in the REST action, is that it can react with different response-formats . REST uses the respond_to. We can see this in the generated controller we got from the above steps.
The format specification can be simply done by appending it to the request.(http://localhost:3000/products/1.xml)

Remember the old days when we used to find the following line in the generated views:
link_to :controller => "products",:action=>"show", :id => product
>>>< href="/products/show/1">Show
Looking to our generated views, we see the following code instead:
<%= link_to 'Show', product_path(product) %>
>>>< href="/products/1">Show
The 'link_to' call is the same, but the hash is replaced by the path_methods.

Same thing for the following methods:
<%= link_to 'New product', new_product_path %>
>>>< href="/products/new">New product

<%= link_to 'Edit', edit_product_path(product) %>
>>>< href="/products/1;edit">Edit
It is not surprising to expect that the REST will affect our forms too. Now, we have to use Path-Methods in our Create/Edit forms.
The :url-hash is replaced with the calling of a Path-Method
  • product-path for the new-form.
  • product_path(:id) for the edit form.
<%= form_for(:product, :url => products_path) do |f| %>
>>>< action="/products" method="post">

<%= form_for(:product, :url => product_path(@product),
:html => { :method => :put }) do |f| %>
>>>< action="/products/1" method="post">
< style="margin: 0pt; padding: 0pt;">
< name="_method" value="put" type="hidden">
< / div>

Finally, the Destroy. The method used for both showing and deleting is 'project-path'. The only difference is that the destroy link additionally uses the parameter :method to name the HTTP method to use (:delete) because the browser doesn't support DELETE.
<%= link_to 'Show', product_path(product) %>
%= link_to 'Destroy', product_path(product),:method => :delete %>
In the same manner controllers have to take special care in using the new technique during redirect operation. Rails uses the URL methods generating a method for each path methos:
project_url for project_path
projects_url for projects_path
redirect_to :controller =>"products", :action=>"show", :id=>@project.id
redirect_to project_url(@project)