iT邦幫忙

DAY 21
1

Ruby on Rails 花招百出系列 第 22

Ruby gem “nested_form” 一次增加多筆資料

今天要分享的是一次多筆增加model資料的方法,使用Ryan Bates的gem “nested_form”,適用的情況例如:

  1. 購物網站的商家,要為商品一次增加許多商品圖片
  2. 待辦事項清單,在清單中要一次增加許多待辦事項

從這裡可以很清楚的看出,如果一次只能新增一張圖片,使用者會超麻煩,也會慢到想殺人;同理,如果待辦事項清單上一次只能增加一個待辦事項,那光讀取頁面的速度,就慢到足以讓人想睡覺了。這時候可以使用nested_form這個gem,在新增附屬的model時可以一次新增許多事項。

安裝:

在Gemfile中安裝nested_form這個gem。

gem "nested_form"

在command line中執行bundle,並且在application.js當中加入要求使用jQuery效果:

//= require jquery_nested_form

建立model的正確關係:

首先,確認兩個model之間有建立正確的關係。首先是event.rb:

has_many :tasks

accepts_nested_attributes_for :tasks,

  :allow_destroy => true,

  :reject_if => :all_blank

再來是task.rb

belongs_to :event

因為我們要在建立event的同時也建立tasks,所以要寫上accepts_nested_attributes,允許在event的new action時,可以同時建立其中的task資料,就可以不用額外建立task的new action。而後方附帶:allow_destroy和:reject_if的選項,前者代表我們能正確減少表單送出的數量,而後者是確保表單空白時,就不會有資料留下。這邊講起來比較模糊,如果各位跟我當初一樣白目的話,就可以先不寫上後面那兩行,等遇到錯誤時......嗯哼!

修改controller:

接下來要在controller中加上允許task的存取,因此我們找到原本scaffold時建立的event_params,在後面加上一些東西,變成:

def event_params

  params.require(:event).permit(:title, :content, :date, :tasks_attributes => [:id, :content, :due, :_destroy])

end

:tasks_attributes把後方[]當中的欄位包起來,其中把:id加入,是為了存取時把所有重複id的task拿掉,以免造成重複資料的建立;而後方的_destroy,是為了配合剛剛我們在model中設定的:allow_destroy選項,讓待會兒我們在設定增加和減少欄位時,可以正確的把欄位減少。

修改view:

在scaffold起來的view當中,我們可以修改event當中的_form.html.erb,讓new和edit都可以使用。一般我們在建立資料時,撰寫form時都是使用form_for這個helper,而在使用nested_form時,要修改成nested_form_for如下:

<%= nested_form_for(@event) do |f| %>

  ......

<% end %>

而在這份表格中,我們要加上:task的表格,讓在建立event時,一同把tasks建立起來。

<%= f.fields_for :tasks do |t| %>

    <p>新待辦事項:</p>

    <p>內容:<%= t.text_field :content %></p>

    <p>截止時間:<%= t.text_field :due %></p>

    <p><%= t.link_to_remove "移除此待辦事項" %></p>

    <hr/>

<% end %>

    <p><%= f.link_to_add "新增待辦事項", :tasks %></p>

上方搭配中文字應該非常清楚了,這個gem最重要的兩個helper,一個是link_to_remove,一個是link_to_add,只要按下『新增待辦事項』的按鈕,就可以增加欄位,為這個event增加更多的task;而如果增加太多欄位,則可以利用『移除此待辦事項』的連結,把不需要的欄位移除。

因為我們在model檔案裡面有加上:reject_if => :all_blank,所以如果把需要填入資料的地方都留白,就不會儲存,同等於把這筆資料刪除;這個方法可以間接用來移除不想要的欄位。如果剛剛的設定有錯誤,可能就會發生一次增加多個欄位、或是明明刪了欄位卻有儲存等窘境,這都是我過來人的無知和痴愚,請大家盡量避免。

以上就是這個nested_form的基本用法,如果有需要進階用法,例如task表格要建立在event之外,則可以利用data-target的設定,讓兩者有關連。所有更多細節的應用部分,請參考Ryan Bates的github檔案


上一篇
Ruby Splat(*)符號使用
下一篇
ActiveRecord Migration撰寫方法
系列文
Ruby on Rails 花招百出32

尚未有邦友留言

立即登入留言