Rails 3 Перестроить вложенные атрибуты из данных формы - PullRequest
1 голос
/ 21 марта 2012

Back-end: у меня есть модель (Пользователь), у которой есть_много другой модели (ContactPreference).Интерфейс: интерфейс, позволяющий пользователю изменять порядок, добавлять и удалять настройки контактов для конкретного пользователя.

Я бы хотел, чтобы пользователь зафиксировал все свои изменения сразу с помощью одной отправки формы.Теперь я делаю это с помощью allows_nested_attributes_for :contact_preferences в модели User и наивно размещаем атрибуты списка отредактированных предпочтений.Он работает просто отлично, за исключением явной ошибки: если пользователь удаляет предпочтение контакта, идентификатор просто не отправляется, и предпочтение не удаляется из БД.

allows_nested_attributes_for поддерживает удаление объектов из коллекции, но требует, чтобы клиент отслеживал, какие идентификаторы были удалены, и передает параметр '_destroy' => 1.Это грязная логика, которой я бы предпочел избежать;Я просто хочу, чтобы объекты были удалены, если они явно не включены в параметры.Насколько я могу судить, allows_nested_attributes_for не поддерживает это поведение, поэтому я пытаюсь реализовать собственное решение.

Какой самый эффективный (с точки зрения доступа к базе данных) способ сделать такое обновление?Удалить все и восстановить список с нуля?Я загружаю ассоциацию и выбираю объекты, которые явно не включены?Возможно, есть какая-нибудь умная магия ActiveRecord, которую я могу использовать?

1 Ответ

1 голос
/ 21 марта 2012

Мое личное мнение таково, что выполнение этого с использованием флага :destroy => 1 намного менее беспорядочно, чем альтернатива.Альтернативой может быть загрузка ассоциации на сервер, сравнение входящих параметров, выяснение, какие записи отсутствуют, затем удаление отсутствующих и обновление оставшихся.Это много лишней логики, операций с БД и, что хуже всего, вам придется вручную переделать accepts_nested_attributes_for, что является нетривиальным подвигом.

HTML даст вам небольшую хитростьвыполнить это без JS.Добавьте флажок к каждой записи с именем :destroy.Используйте высокоуровневые помощники форм, например, check_box, а не check_box_tag (что требует много вещей, чтобы получить право вручную), или помощник по формам более высокого уровня, такой как simple_form gem .

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

Вы не сказали много о своем переднемкод конца;Похоже, у вас там куча JS.Вы, вероятно, скрываете запись, когда пользователь «удаляет» ее, вы можете просто программно добавить флаг destroy в этом случае, если вы не хотите использовать метод флажка выше.Это будет намного проще и менее подвержено ошибкам, чем попытка угадать поведение бэкэнда.

...