2016-07-29 65 views
0

我有PizzaTopping連接表的Pizza模型和Topping模型。披薩有許多配料,頂部屬於披薩。我是Rails的新手。如何使用複選框創建嵌套窗體的多個記錄

我的問題是試圖瞭解如何創建一個嵌套的表單,將多個記錄添加到我的PizzaTopping連接表中。我還需要以複選框的形式顯示澆頭。

<div class="form-horizontal"> 
    <%= form_for(@pizza) do |f| %> 

混亂#1:

要我理解這是爲了顯示覆選框,該工作的完整模型,但我對控制器如何接受這個困惑,並在此加入記錄與披薩相關的配料表。我想單獨的記錄(而不是即摘心IDS的陣列的屬性):

PizzaTopping.create(id: 1, pizza_id: 1, topping_id: 1) 
PizzaTopping.create(id: 2, pizza_id: 1, topping_id: 2) 
PizzaTopping.create(id: 3, pizza_id: 1, topping_id: 3) 

..

<div class="form-group"> 
    <%= f.collection_check_boxes(:topping_ids, Topping.all, :id, :name) do |b| %> 
     <%= b.check_box %> 
     <%= b.label %> 
    <% end %> 
    </div> 

或混亂#2:

這是一個嵌套的形式,但如何我是否可以從Topping模型的複選框中獲得澆口,並且如上所示,我如何在控制器中編寫此代碼以在連接表中添加記錄。

<div class="form-group"> 
    <%= f.fields_for :toppings do |builder| %> 
    <%= builder.check_box %> // confused what I would even do next 

    <% end %> 
</div> 

...

<%= f.submit %> 
    <% end %> 
</div> 
+0

所以,你想創建在同一個形式的披薩和澆頭? –

+0

我有一個單獨的模型,可以添加配料和去除澆頭。爲此,我只想創建一個比薩餅,創建一個表格,以Topping模型中的所有澆頭的複選框格式列出。然後能夠用它的澆頭儲存披薩 – ravip0711

回答

1

首先讓我們通過pizza_toppings表設置間接的多對多關係。

class Pizza < ActiveRecord::Base 
    has_many :pizza_toppings 
    has_many :toppings, through: :pizza_toppings 
end 

class Topping < ActiveRecord::Base 
    has_many :pizza_toppings 
    has_many :pizzas, through: :pizza_toppings 
end 

class PizzaTopping < ActiveRecord::Base 
    belongs_to :pizza 
    belongs_to :topping 
end 

這是什麼實現的是,它可以讓你任意數量的比薩餅與任意數量的澆頭的關聯和ActiveRecord的將處理加入你:

@pizza = Pizza.find_by(name: 'Vesuvio') 
@pizza.toppings 
# => Topping(name: cheese) ... 
@pizza.toppings << Topping.find_by(name: 'Ham') 
# inserts a record into the pizza_toppings table 
# you can also do the inverse 
@topping = Topping.find_by(name: 'Anchovies') 
@topping.pizzas 
# => Pizza(name: 'Napoli') 

要設置一個對任何或多對多的關係通過複選框,您可以使用collection_check_boxes helper

<% form_for(@pizza) do |f| %> 
    <% f.collection_check_boxes(:topping_ids, Topping.all, :id, :name) %> 
<% end %> 

當你給一個模型has_many協會它得到_ids二傳手這需要一組ID,並添加/刪除關聯,在這種情況下的ActiveRecord也足夠聰明,知道它應該設置通過協會在使用through選項時連接表。

由collection_check_boxes生成的複選框僅爲您提供 - 包含所選澆頭標識的參數中的數組。

請注意,您不需要在這裏使用fields_for,除非您打算讓用戶在同一頁上創建比薩餅和澆頭。另外請確保您將參數topping_ids白名單。

def pizza_params 
    params.require(:pizza).permit(:name, topping_ids: []) 
end 

現在你讓我都餓了。

+0

謝謝先生!這是一項工作中的編碼挑戰,我試圖在他們給我的存儲庫(它沒有「直通」關係)中關注他們的模型。我試圖通過挑戰來繞過它,但除了創造這種「通過」關係外,沒有別的辦法。挑戰是開放式的,所以我們會看到他們對它的接受程度。 =) – ravip0711

+0

恕我直言 - 使用連接表,並設置與'通過:'的關係是在ActiveRecord中執行M2M關係的正確方法。他們在故意做錯的地方有一個很好的機會。 – max

0

首先第一件事情,如果你使用一個連接表,那麼你需要不同的方式組織你的關係,這是沒有意義的使用連接表用belongs_to的關係,你想要做的是組織你的關係,以便比薩has_many:澆頭,和Topping has_many:比薩餅,並使用through :: pizza_toppings鍵。

現在進入第一個混淆狀態 如果您使用的是複選框,您希望收到的最多值是該複選框的值,最有可能是ids,然後在您擁有該數組後立即實例化記錄的ids,或許是沿着selected_toppings = Topping.where(id: params[:topping_ids])的行,它將實例化所選擇的澆頭的集合。 此外,如果你有正確的關係設置,沒有必要明確創建PizzaTopping記錄,這是一個連接表,在我看來,我更喜歡處理所有使用關係的東西,沿線pizza.toppings << selected_toppings應該做的伎倆把它全部設置好。

困惑二: 我不認爲你在找什麼是一個嵌套的形式,因爲你實際上並沒有創建澆頭,你只是想要一個澆頭列表與一個比薩相關。嵌套表單是當你想創建/編輯然後編寫一個關係的屬性,你的澆頭已經預先設置好的時候,所以只需用正確的形式將複選框與你的澆頭標識符的值相關聯即可。

希望這會有所幫助!

相關問題