在Rails中,常常會用到表單(form)將資料傳入資料庫,其中在Rails 5.1版本之前,常用的就是form_tag
與form_for
,我們來看看他們的分別該在何時使用:
先說結論:
form內 有 model實體時,用
form_for
,主要用於新增或修改。form內 無 model實體時,用
form_tag
,主要用於登入一筆資料。Rails 5.1後,將兩者結合為
form_with
關於form_with
,有機會我再來對它做補充,這次先針對form_for
及form_tag
。
form內有model實體時,用form_for
,Rails會根據Model的屬性,自動判斷按下submit後,是要新增還是更新Model裡的資料。
翻譯蒟蒻:有媽豆的實體就用form_for
#products_controller.rb
#@product = Product.new
<%= form_for @product do |form| %>
<%= form.text_field :title %>
<%= form.submit %>
<% end %>
html會幫你產生
<form class="new_product" id="new_product" action="/products"
accept-charset="UTF-8" method="post"><input name="**utf8**" type="hidden" value="✓">
<input type="hidden" name="**authenticity_token**" value="kxDHc4ID2xFAfBXANcrXBpqtI/
6rerAkMBaCh64j+O6LXsucFvkpU/UxO78XW8ELRuOwAU6O/MEM1LUdK9yEeQ==">
<input type="text" name="product[title]" id="product_title">
<input type="submit" name="commit" value="Create Product" data-disable-with="Create Product">
</form>
來簡單看看上面程式碼:
第一個 name 屬性為 utf8 的 input,強制瀏覽器正確採用表單指定的編碼。
第二個 name 屬性為 authenticity_token 的 input,
是 Rails 內建用來防止 CSRF (cross-site request forgery protection) 攻擊的安全機制。
為何要有這樣的保護機制: CSRF跨站請求偽造 Cross-site request forgery
這樣設定好整個表格,就是為了將@product這個ActiveRecord資料而設定的,所以表格送出的params會將我們在表格內填的變數,整個包在product物件下面,才會需要使用Strong Parameter那樣的機制將product變數抽出做permit(避免CSRF攻擊):
def product_params
params.require(:product).permit(:title, :password)
end
form內無model實體時,用form_tag
,得指定要傳入哪個連結的action
來進行表單資料的傳送。
翻譯蒟蒻:沒有媽豆的時候就只能用form_tag
<%= form_tag url:new_product_path do %>
<%= text_field_tag :title %>
<%= submit_tag %>
<% end %>
<form action="/products/new?url=%2Fproducts" accept-charset="UTF-8"
method="post"><input name="utf8" type="hidden" value="✓">
<input type="hidden" name="authenticity_token" value="lfORCE9tuYA4Yuda6EziGw
KMQk9flV9dkM4ogaEzmUCNvZ3n25dLwo0vySXK3fQW3sLRsLphE7isDB8bJMzl1w==">
<input type="text" name="title" id="title">
<input type="submit" name="commit" value="Save changes" data-disable-with="Save changes">
</form>
如果是使用form_tag,變數就不會包在任何東西內,可以直接在controller當中取用:
def search
@products = Product.where(product: params[:search])
end
參考資料:
Ruby API: form_tag
Ruby API: form_for
Rails 5.1's form_with vs. form_tag vs. form_for
form_tag 是啥?跟 form_for 有什麼不一樣?
“A man can get discouraged many times, but he is not a failure until he begins to blame somebody else and stops trying.”
— John Burroughs, Writer
本文同步發佈於: https://louiswuyj.tw/