Signup form HTML
這節來瞭解一下 form_for 的構成。
form_for 是由 ERb 調用該方法,結尾是 end:
<%= form_for(@user) do |f| %>
.
.
.
<% end %>
do 關鍵字指出 form_for 接受一個 block 帶著一個參數 f。f 的作用就是產生相對應的 HTML 元素,例如:
<%= f.label :name %>
<%= f.text_field :name %>
這兩行會產生 @user 物件的 label tag、input。
如果查看 HTML 原始碼的話會長這樣:
<form accept-charset="UTF-8" action="/users" class="new_user"
id="new_user" method="post">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden"
value="NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=" />
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />
<label for="user_email">Email</label>
<input id="user_email" name="user[email]" type="email" />
<label for="user_password">Password</label>
<input id="user_password" name="user[password]"
type="password" />
<label for="user_password_confirmation">Confirmation</label>
<input id="user_password_confirmation"
name="user[password_confirmation]" type="password" />
<input class="btn btn-primary" name="commit" type="submit"
value="Create my account" />
</form>
所以剛剛的:
<%= f.label :name %>
<%= f.text_field :name %>
最後會被輸出成:
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />
之後會講到,之所以可以建立使用者,是因為 input 的 name 屬性:
<input id="user_name" name="user[name]" - - - />
.
.
.
<input id="user_password" name="user[password]" - - - />
Rails 以這些 name 的屬性值作為 key,而使用者輸入的資料為 value,建構出一個叫 params 的 hash,用來建立使用者。
Rails 使用 @user 物件建立 form tag,因為 Ruby 物件會知道自己屬於哪一個 class,所以 Rails 知道 @user 的 class 是 User。此外,因為 @user 是一個新的使用者,所以 Rails 知道在 form 上使用 post 方法,這正是建立新物件所需要的 HTTP 請求:
<form action="/users" class="new_user" id="new_user" method="post">
上面的 action="/users" 和 method="post",會讓 Rails 向 /users 發送 POST 請求。
form tag 下面還會有這段程式碼:
<div style="display:none">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden"
value="NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=" />
</div>
這段程式碼不會顯示在瀏覽器中,只對 Rails 內部有用。它使用 Unicode 字串 ✓ (a checkmark ✓)強制瀏覽器使用正確的字串編碼提交資料。authenticity token 是 Rails 用來防禦 Cross-Site Request Forgery,簡稱 CSRF。