瞭解Scaffold 的程式流程是怎麼跑後, 再來就由它的程式碼來學習囉~
先看下述幾個頁面:
下述的內容可搭配此圖一起看:
![]()
程式進入點是 /posts 或 /posts.xml 預設就是會跑 Controller index function.
先看 Controller: app/controllers/posts_controller.rb 的 index function.
class PostsController < ApplicationController
# GET /posts
# GET /posts.xml
def index
@posts = Post.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @posts }
end
end
end
由此可知 Controller 是繼承自 ApplicationController(app/controllers/application.rb), 而註解寫到的就是存取此 index 可以用 GET /posts 和 GET /posts.xml 兩種方式, 來分別看到 View 的 Template 結果和 XML 結果.
def index
def index 是 function, 到底是對應到哪個頁面, 可由下述步驟查詢:
bash$ rake routes 可以看到:
此處的 def index
就是 routes 的 :action => "index"
@posts = Post.find(:all)
到此處時, 這邊就是使用到 Model 的 Post class, 這段程式的流程會從 Post.find(:all) 直接進入 Model, 完成後再繼續下面的處理.
於 Post.find(:all) 可見: Model: app/models/post.rb, 程式碼只有下面2行:
class Post < ActiveRecord::Base
end
find() 這是於 ActiveRecord 的 function, 因為 class Post 是繼承自 ActiveRecord, 所以可直接使用, 也是於此做其它資料正確性的檢查.
respond_to do |format|
再來看最後輸出, 要輸出前為何還要加 respond_to? 且同一個 function 是如何輸出兩種不同的結果?
於程式可以看到 respond_to 裡面有包兩個輸出檔: format.html / format.xml, 由此可知是由此產生 HTML/XML 檔輸出.
respond_to 判斷何時要送 HTML, 何時要送 XML, 主要是靠 "HTTP 的 Accept-Type", 若不用 respond_to 的話, 程式得要改寫成下述:(參考: REST on Rails指南5: respond_to)
def index(client_format)
@posts = Post.find(:all)
if client_format == "text/html"
# TO DO: render the default template
elsif client_format == "application/javascript"
# TO DO: return some javascript
elsif client_format == "application/xml" || client_format == "text/xml"
# TO DO: return some XML back the client
# ... more elsif statements here for each MIME type you want to support
end
end
因為 respond_to 處理掉上述的事情, 所以就可以用下述存取看看, 就可以得到不同的結果:
format.html # index.html.erb
於 format.html 這邊, 它就會去讀取 View 的 index.html.erb 檔, 而 View 裡面也有固定的 Layout file 做定義.
先看 Layout file: (只看 body 部份)
<body>
<p style="color:green"><%= flash[:notice] %></p>
<%= yield %>
</body>
此段變數的訊息會從 Controller 取出, 於 Create / Update 的 Controller 完成後, 就會看到 Post was successfully created. 等訊息.
而此行, 就會把 View 的內容放進去(取代 yield), 例如 View 的編輯頁面:
View: app/views/posts/edit.html.erb, 內容大致如下:
<%= error_messages_for :post %>
<% form_for(@post) do |f| %>
<p>
<b>Id</b><br />
<%= f.text_field :id %>
</p>
此行就是 Model 有錯誤時, 錯誤訊息(:message)會於此印出. ex: 若於 Model 加入此段: validates_length_of :title, :minimum => 20, :message => "最少要 %d 字元", 那 title 若沒有輸入超過 20個字, 就會顯示錯誤訊息(若有任何錯誤, 資料就不會被新增/修改).