Ruby on Rails 4 полета_за брой повторения

Бих искал да покажа формуляр с четири вложени набора полета за свързани обекти. Единственият начин, който открих, е да заменя метода initialize и да дефинирам четири асоциации:

РУБИН

def initialize(attributes = {})
  super
  4.times { items << Item.new }
end

и след това покажете нормално вложените полета:

HAML

= f.fields_for :items do |item|
  = render 'item_fields', f: item

Това не работи, когато се опитвам да редактирам обекти, които вече съществуват и имат по-малък брой свързани елементи.

Всяка помощ ще бъде оценена.

ПОВЕЧЕ ИНФОРМАЦИЯ:

Order has_many items
OrderSet has_many orders

Поръчките се добавят чрез cocoon скъпоценен камък (има поне една поръчка във всеки комплект)

Винаги трябва да има четири елемента за всяка поръчка. Но когато има по-малко елементи, не искам да запазвам празни записи, вместо това бих искал просто да покажа оставащите елементи като празни.


person jmarceli    schedule 06.04.2015    source източник


Отговори (2)


Инициализирането не е мястото, тъй като се изпълнява всеки път, когато се създава нов Order екземпляр, това означава: също и при извличане на съществуваща поръчка от базата данни.

Имхо гледката също не е оптималното място.

Бих решил това в контролера:

def new
  @order = Order.new
  4.times { @order.items.build }
end

и след това можете просто да оставите своя модел/изглед така, както са били първоначално.

Ако винаги искате да показвате 4 вложени елемента, можете да направите нещо подобно в действието за редактиране (за да попълните до 4)

def edit
  @order = Order.find(params[:id])
  (@order.items.length...4).each { @order.items.build }
end

По мое лично мнение това е по-чисто, отколкото да го правите в изгледа.

[РЕДАКТИРАНЕ: очевидно това е двойно вложена форма]

И така, във вашия коментар вие изяснихте, че това е двойно вложена форма, в такъв случай бих използвал : wrap_object опция, както следва (става малко трудно да напишеш приличен пример тук, без да даваш повече подробности, така че ще го направя кратък и се надявам да е ясен). Предполагам, че имате формуляр за „нещо“, с link_to_add_association за :orders и тази поръчка трябва да има няколко (4) елемента, така че можете да направите нещо като:

= link_to_add_association('add order', f, :orders,
:wrap_object => Proc.new { |order| 4.times { order.items.build}; order })
person nathanvda    schedule 06.04.2015
comment
За съжаление не е възможно, защото Order, който е родителски модел за items, е допълнително вложен, така че никога не изпълнява действие new. За да бъдем по-точни, orders се добавят динамично от cocoon скъпоценен камък (наистина хубав скъпоценен камък, благодаря) към неговия родителски модел, да кажем OrdersSet. - person jmarceli; 06.04.2015
comment
Що се отнася до мен, coocon генерира полета само въз основа на шаблона, но може и да греша. - person jmarceli; 06.04.2015
comment
В такъв случай трябва да използвате опцията :wrap_object. Вижте редакцията, която направих. - person nathanvda; 06.04.2015
comment
Това изглежда обещаващо. Ще докладвам, след като го приложа към моя код. - person jmarceli; 06.04.2015
comment
Благодаря много. Това :wrap_object ми дава цялата мощност, от която се нуждая, за да разреша този проблем. - person jmarceli; 06.04.2015
comment
Още нещо @order.items << Item.new незабавно извършва промени в DB. Може би знаете някакво добро решение? - person jmarceli; 06.04.2015
comment
О, да, наистина, но само ако @order вече е запазен. Можете да използвате @order.items.build вместо това. Ще адаптирам поста си съответно. - person nathanvda; 06.04.2015
comment
Напълно несвързано, просто любопитно: защо използвате потребителско име по подразбиране? - person nathanvda; 07.04.2015
comment
Нека продължим тази дискусия в чата. - person jmarceli; 07.04.2015

Преди вашия f.fields_for във вашия изглед или дори във вашия контролер, можете да проверите дължината на .items() и да създадете нови обекти според изискванията:

(o.items.length...4).each { f.object.items << Item.new}
= f.fields_for :items do |item|
 = render 'item_fields', f: item
person ilan berci    schedule 06.04.2015
comment
Благодаря. Това е хубаво, но вероятно ще се придържам към отговора на @nathanvda, защото в крайна сметка използвам неговия cocoon gem за тази форма. - person jmarceli; 06.04.2015