REST 風格的URL 和View
View是系統界面和用戶之間的一個表現,用戶通過鏈接和按鈕來和系統進行交互。傳統上Rails的開發人員使用 link_to 這個helper 方法來構造一個鏈接,這個方法需要一個 hashmap, hashmap 由 controller 和 action 組成;此外,還可以傳遞一些其他的參數。例如:
??? link_to :controller => "projects", :action => "show", :id => project
??? =>
??? <a href="/projects/show/1">Show</a>
我們馬上就意思到,這個link_to 方法并不能很好的用于我們的REST思想:REST不會在URL里包含action。
那么重要的就是通過鏈接和按鈕,我們要把 http 協議的4個動作和URL一起傳遞給服務器。所以,我們會看到Rails的改進之處:我們仍然使用 link_to 去創建鏈接,但是,我們不會再使用hashmap, 而是使用一個“path”的方法。首先用一個例子,來說明如何創建一個鏈接去調用 controller 的 show action。請看好,我
們不會再使用 controller, action, 和 id 了:
??? link_to "Show", project_path(project)
??? =>
??? <a href="/projects/1">Show</a>
關于 path 和下面要說的url 這兩類helper 方法,請大家千萬不要疑惑他們是從哪來的。我們可以這么認為,是Rails 動態地創造了他們。我們只要使用就可以了!
傳統的link_to 所生成的鏈接中包含了controller和action,相對比,使用新的 “project_path” 所創建的鏈接,只包含了controller 和 資源的id –毫無疑問,這是一個 REST風格的URL。因為鏈接默認的是一個“Get”請求,Rails 能夠知道這一點,所以就會去調用 show action。對于每一個資源,rails 都會有7個標準的 path 方法,這些可以從表1.2中看到。

進一步看看這個表,我們也會發現4個http 動作,并不足以包含全部的CRUD操作。前2個方法使用Get的方式會工作的很好,但是對于new_project_path 和 edit_project_path 就不同了。
New 和 Edit
用戶如果點擊一個“新建”鏈接,那么會使用Get動作來對服務器發送一個請求。下面的例子表明,生成的鏈接是由 controller 和一個“new”action 組成的。
link_to "New", new_project_path
=>
<a href="/projects/new">New</a>
這是對REST思想的一種破壞?或許乍看之下確實如此。但是如果你仔細看,那么一切都會清晰,“new”并不是一個CURD的action,它更像一個建立一個新的資源之前的準備的動作。真正的CRUD 中的create被調用,是在新的form被提交的以后才執行的。這個鏈接當然也沒有資源的id—因為資源還沒有被創建。一個鏈接如果沒有資源的id,那么就不應該被稱為REST的URL,因為REST的URL總是會指定一個資源的id。所以,這個 “new” action 僅僅因該用來顯示一個新的form的頁面而已。
對于 edit_project_path ,也是同樣的道理。它引用了一個資源,但是僅僅是在調用 update action 之前的準備工作。真正的update action 是在頁面被提交以后才執行的。edit_project_path 和 new_project_path 唯一的區別就是前者需要使用一個資源的id。按照REST的規則,資源的id放在controller 的后面:/project/1 。但是如果僅僅使用Get 動作來提交這個URL,那么Rails將會認為你要調用的是show action。為了防止這一點,edit_project_path 方法擴展了一下生成的鏈接,例如:
link_to "Edit", edit_project_path(project)
=>
<a href="/projects/1;edit">Edit</a>
這樣,我們就能理解為什么允許 edit_project_path 和 new_project_path生成的鏈接里帶有 action 了,因為他們兩個都不是REST的 CRUD URL,他們僅僅是準備工作。還有其它的一些URL和這兩個很相似,我們會在后面的章節介紹。
在 form 中使用 path 方法:Create 和 Update
傳統的方式上,我們使用 form_tag 或 form_for 來創建一個form:
<% form_for :project, @project, :url => { :action => "create" } do |f|
%>
...
<% end %>
在REST應用中,這個 :url hashmap 會被 path 方法給取代:
“project_path” 創建新的資源所使用的form
“project_path(:id)”編輯一個資源所使用的form
a) 創建資源所使用的form
form 使用 post 動作向服務器提交信息,“project_path”方法并不會有資源id作為參數,這樣,生成的URL就應該是“/projects”這個樣子。當提交到服務器以后,就會調用 create action。
form_for(:project, :url => projects_path) do |f| ...
=>
<form action="/projects" method="post">
b) 編輯一個資源所使用的form
按照REST的思想,一個更新的操作是使用http協議的PUT動作來發送的。但是,正如我們所知道的,瀏覽器只明白 Post和Get動作。解決的辦法就是使用
form_for 方法里的 :html 參數。
form_for(:project, :url => project_path(@project),
:html => { :method => :put }) do |f| ...
=>
<form action="/projects/1" method="post">
<div style="margin:0;padding:0">
<input name="_method" type="hidden" value="put" />
</div>
Rails 生成了一個隱藏的字段來代替http的put 動作。提交以后,Rails 會檢查這個變量,然后判斷是否去調用update方法。
刪除
恐怕我們已經發覺了,用于顯示和刪除一個資源,所使用的path方法都一樣:
link_to "Show", project_path(project)
link_to "Destroy", project_path(project), :method => :delete
唯一的不同就是 刪除的時候,使用了一個變量 :method,用它來表示http的DELETE動作。因為瀏覽器不支持DELETE動作,所以,Rails 會生成一些javascript來解決這個問題:
link_to "Destroy", project_path(project), :method => :delete
=>
<a href="/projects/1"
onclick="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);f.submit();
return false;">Destroy</a>
這段javascript 會生成一個form,把 http 的DELETE動作放在隱藏變量里傳遞給服務器,然后,Rails 會判斷這個變量,決定是否去調用destroy 方法。
好了,今天就介紹到這,明天我們來說說Controller中的URL方法。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
