Rails2でのrouting ActionController::Resources
Resources
ActionController::Resourcesを使用することで、GET、POST、PUT、DELETEに対応したRestfulなリソースが動的に生成される。
map.resources :products
とconfig/routes.rbに記述すると、以下のリソースが生成される。
Named Route | Method | URL | 対応するコントローラとアクション |
---|---|---|---|
products | GET | /products | {:controller=>"products", :action=>"index"} |
formatted_products | GET | /products.:format | {:controller=>"products", :action=>"index"} |
POST | /products | {:controller=>"products", :action=>"create"} | |
POST | /products.:format | {:controller=>"products", :action=>"create"} | |
new_product | GET | /products/new | {:controller=>"products", :action=>"new"} |
formatted_new_product | GET | /products/new.:format | {:controller=>"products", :action=>"new"} |
edit_product | GET | /products/:id/edit | {:controller=>"products", :action=>"edit"} |
formatted_edit_product | GET | /products/:id/edit.:format | {:controller=>"products", :action=>"edit"} |
product | GET | /products/:id | {:controller=>"products", :action=>"show"} |
formatted_product | GET | /products/:id.:format | {:controller=>"products", :action=>"show"} |
PUT | /products/:id | {:controller=>"products", :action=>"update"} | |
PUT | /products/:id.:format | {:controller=>"products", :action=>"update"} | |
DELETE | /products/:id | {:controller=>"products", :action=>"destroy"} | |
DELETE | /products/:id.:format | {:controller=>"products", :action=>"destroy"} |
Named Route | Helpers |
---|---|
products | products_url, hash_for_products_url, products_path, hash_for_products_path |
product | product_url(id), hash_for_product_url(id), product_path(id), hash_for_product_path(id) |
new_product | new_product_url, hash_for_new_product_url, new_product_path, hash_for_new_product_path |
edit_product | edit_product_url(id), hash_for_edit_product_url(id), edit_product_path(id), hash_for_edit_product_path(id) |
これらを使うと、例えば以下の用に記述することができます。
redirect_to :contorller => 'products', :action => 'index' # ↓ redirect_to products_url
<%= link_to "Edit", :controller => 'products', :action => 'edit', :id => @product %> # ↓ <%= link_to "Edit", edit_product_url(@product) %>
さらに、form_forを使うともっと素敵な事が起こるのです。
・new.html.erb
<h1>New product</h1> <% form_for(@product) do |f| %> <%= f.error_messages %> <p> <%= f.label :name %><br /> <%= f.text_field :name %> </p> <p> <%= f.label :comment %><br /> <%= f.text_area :comment %> </p> <p> <%= f.submit "Create" %> </p> <% end %>
・edit.html.erb
<h1>Editing product</h1> <% form_for(@product) do |f| %> <%= f.error_messages %> <p> <%= f.label :name %><br /> <%= f.text_field :name %> </p> <p> <%= f.label :comment %><br /> <%= f.text_area :comment %> </p> <p> <%= f.submit "Update" %> </p> <% end %>
上記の2つのform_forは一見同じに見えますが、それぞれのアクションを実行すると
・/products/new
<form action="/products" class="new_product" id="new_product" method="post"> <div style="margin:0;padding:0"> <input name="authenticity_token" type="hidden" value="f0a853363c1b8ec3e060051b00d57b07a0a5bf4c" /> </div> <p> <label for="product_name">Name</label><br /> <input id="product_name" name="product[name]" size="30" type="text" /> </p> <p> <label for="product_comment">Comment</label><br /> <textarea cols="40" id="product_comment" name="product[comment]" rows="20"></textarea> </p> <p> <input id="product_submit" name="commit" type="submit" value="Create" /> </p> </form>
・/products/1/edit
<form action="/products/1" class="edit_product" id="edit_product_1" method="post"> <div style="margin:0;padding:0"> <input name="_method" type="hidden" value="put" /> <input name="authenticity_token" type="hidden" value="f0a853363c1b8ec3e060051b00d57b07a0a5bf4c" /> </div> <p> <label for="product_name">Name</label><br /> <input id="product_name" name="product[name]" size="30" type="text" value="test" /> </p> <p> <label for="product_comment">Comment</label><br /> <textarea cols="40" id="product_comment" name="product[comment]" rows="20">testだよ</textarea> </p> <p> <input id="product_submit" name="commit" type="submit" value="Update" /> </p> </form>
アクションに応じて、formも動的に変化しているです。素晴らしい。
因みに、見てわかるようにPUTやDELETEはブラウザが対応していないので、隠し要素へput、deleteの値を入れて送信することで実現されています。
new、show、edit、destoryへのリンクは以下のように展開されます。
#new <%= link_to 'New', new_product_url %> # ↓ <a href="/products/new">New</a> # show <%= link_to 'Show', product_url(@product) %> # ↓ <a href="/products/1">Show</a> # edit <%= link_to 'Edit', edit_product_url(@product) %> # ↓ <a href="/products/1/edit">Edit</a> #destory <%= link_to 'Destroy', product_url(@product), :method => 'delete' %> # ↓ <a href="/products/1" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'f0a853363c1b8ec3e060051b00d57b07a0a5bf4c'); f.appendChild(s);f.submit(); };return false;">Destroy</a>
ということでここまでは、scaffoldで生成されるコードで同じものが確認可能なので、実際のコードを確認したい場合は、以下のとおり実行して下さい。
$ ./script/generate scaffold product name:string comment:text
最後にURLへのパラメータの追加は以下の様になります。
<%= link_to, 'Show', :controller => 'products', :action => 'show', :id => @product, :lang => 'jp' %> # ↓ <%= link_to, 'Show', product_path(@product, {:lang => 'jp'}) %> # ↓ <a herf="/products/1?lang=jp">Show</a>
関連エントリー
- Resourcesのオプション - Cafe L@ Bebop
- Resourcesのネスト
- Napaspace Route