iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 17
1
自我挑戰組

非本科之30天Ruby / Rails學習筆記系列 第 17

Day17: 淺談Rails的表單: form_for? form_tag?

  • 分享至 

  • xImage
  •  

在Rails中,常常會用到表單(form)將資料傳入資料庫,其中在Rails 5.1版本之前,常用的就是form_tagform_for,我們來看看他們的分別該在何時使用:

先說結論:

form內 model實體時,用form_for,主要用於新增或修改。

form內 model實體時,用form_tag,主要用於登入一筆資料。

Rails 5.1後,將兩者結合為form_with

關於form_with,有機會我再來對它做補充,這次先針對form_forform_tag

form_for

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_tag

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/


上一篇
Day16: 淺談Rails裡的resources
下一篇
Day18: 淺談Rails的表單: form_with
系列文
非本科之30天Ruby / Rails學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言