Динамический check_box с использованием field_for в рельсах

У меня есть связь "многие ко многим" с блоком ссылок, и я хочу объединить эти модели в одну форму, чтобы я мог обновляться с одной страницы. Я действительно изо всех сил пытаюсь заставить check_box даже показывать все элементы моего массива - я искал сеть и работал над этим буквально весь день, и мне трудно применить информацию, которую я читаю к моя проблема. Я также чрезвычайно новичок в RoR, и я следил за немного устаревшим видеоуроком (до 2.0), поэтому извиняюсь за мой код. До сих пор у меня была возможность вывести только одну пару ключей в массиве (последнюю) - хотя вне формы код, используемый в руководстве, работает именно так, как и должен. Это мало пользы, хотя! Хост - это модель, для которой предназначена основная форма, а биллинг - это внешняя модель, которую я пытаюсь добавить в форму.

Это код, который работает вне формы из учебника:

<% for billing in @billings -%>
<%= check_box_tag('billing_title[]', billing.id, @host.billings.collect
{|obj| obj.id}.include?(billing.id))%> <%= billing.title %><br />
<% end -%>

Мне просто нужно знать, как заставить это работать внутри формы. Это вышеупомянутый код, который извлекает последнюю пару ключей массива после их циклического прохождения:

<% f.fields_for :billings do |obj| %><br />
<%= check_box_tag('billing_title[]', billing.id, @billings.collect
{|obj| obj.id}.include?(billing.id))%> <%= billing.title %><br />
<% end %>

Отладка (@billings):

--- 
- !ruby/object:Billing 
attributes: 
title: Every Month
id: "1"
attributes_cache: {}

- !ruby/object:Billing 
attributes: 
title: 12 Months
id: "2"
attributes_cache: {}

- !ruby/object:Billing 
attributes: 
title: 6 Months
id: "5"
attributes_cache: {}

Любая помощь действительно ценится.

3 ответа

Решение

Крейг, звучит так, как будто вы ищете, является acceptpts_nested_attributes_for, который является гораздо лучшим способом обработки вложенных моделей в форме.

Вместо того, чтобы просто украсть всю работу Райана и опубликовать ее здесь, я просто дам вам ссылку на его скринкаст:

http://railscasts.com/episodes/196-nested-model-form-part-1

Это основано на его сложных сериях форм.

Вы должны быть в состоянии рассказать этот урок тому, что вы пытаетесь сделать, но если нет, я буду рад помочь.

РЕДАКТИРОВАТЬ:

Хорошо, после просмотра вашего кода, есть несколько вещей, вызывающих у вас проблемы.:)

Прежде всего, с ассоциациями вам не нужно тянуть дополнительную коллекцию для выставления счетов, то есть:

@host = Host.find(params[:id])
@voips = Voip.find(:all)
@custsupps = Custsupp.find(:all)
@payments = Payment.find(:all)
@billings = Billing.find(:all) # <-- This is not needed and causing your problems

Настройка ассоциации в модели делает все это за вас. Это часть магии рельсов.:D

Теперь важно отметить, что при использовании ассоциаций необходимо убедиться, что объекты действительно связаны. Другими словами, если у вас есть 3 объекта Billings в вашей базе данных, и они не связаны с вашим объектом Host, они не будут отображаться в форме.

Если вы пытаетесь связать биллинг с Хостом с помощью флажка, вы захотите использовать другой подход, потому что в вашей форме отображаются только Биллинги, уже связанные с вашим Хостом.

Если вы просто пытаетесь отредактировать или изменить существующие Биллинги, которые связаны с Хостом, где флажок представляет, например, "платный" атрибут (логический), тогда этот подход хорош, и код вашей формы будет выглядеть примерно так:

<% f.fields_for :billings do |b| %><br />
  <%= b.check_box :paid %> <%= b.title %>
<% end %>

Поэтому, возможно, уточнить, что вы пытаетесь достичь с точки зрения функциональности, и мы сможем найти лучшее решение.

Я не уверен в своем ответе, но я попробую...

<% f.fields_for :billings, @billings do |obj| %>
   # ...
<% end %>

Похоже, это проблема с петлями for...

В вашем примере кода вы перебираете @billings (массив объектов биллинга, переданных с вашего контроллера), и вызов текущего billing,

В коде формы вы проходите через :billings (символ, относящийся к биллингу ActiveRecords) и вызов текущего obj, Затем, в замешательстве, ваш код повторно использует имя переменной obj снова в функции @billings.collect... но она должна иметь локальную частную область видимости и не влиять на ваш основной цикл, но ее трудно интерпретировать на месте.

В любом случае, поскольку содержимое внутри цикла формы не ссылается obj, это использует переменную billing- которая не изменяется при циклическом переходе, но сохраняет последнее значение: последний элемент из предыдущего цикла! Это объясняет, почему вы видите только последний тег. (Так же debug(@billings) функция делает свой собственный цикл по записям сортировки - она ​​не находится внутри цикла fields_for do.)

Я бы начал с изменения первой строки кода вашей формы, чтобы повторно использовать имя переменной billing опять вот так:

<% f.fields_for :billings do |billing| %><br />

Поначалу блочный синтаксис может быть довольно запутанным - или, черт возьми, всякий раз, когда вы читаете код, который вы не написали сами, - но когда вы разбиваете все это на базовые компоненты, обычно это просто циклически перебирает набор элементов и выполнение некоторой функции на каждом. Также следите за путаницей между похожими именами: @billing, @billings,:billings и billings - это разные вещи для Ruby и Rails. Удачи!

Другие вопросы по тегам