Использование вложенных атрибутов для простого выбора ассоциаций в форме

Я пытаюсь создать вложенную форму атрибута для создания модели, которая в первую очередь является связующим звеном между двумя другими моделями. В моем случае модели представляют books, awardsи модель "разъем" book_awards, Когда я редактирую книгу, я хочу быстро выбрать, какие награды она получила.

Я использую http://railscasts.com/episodes/196-nested-model-form-part-1 чтобы помочь мне начать, но я боюсь, что застрял.

Другой вопрос SO, который кажется похожим, это acceptpts_nested_attributes_for с find_or_create? К сожалению, это также не совсем то, что я делаю, и я не смог адаптировать это.

Мои модели выглядят так. У каждой модели есть дополнительные атрибуты, проверки и т. Д., Но я удалил их для ясности.

class Book < ActiveRecord::Base
  has_many :book_awards
  accepts_nested_attributes_for :book_awards, :allow_destroy => true
end

class Award < ActiveRecord::Base
  has_many :book_awards
end

class BookAward < ActiveRecord::Base
  belongs_to :book, :award
end

В моей книге методы контроллера для редактирования и новые, и случаи сбоя для создания и обновления у меня есть строка @awards = Award.all,

На мой взгляд, я хотел бы видеть список всех наград с флажками рядом с ними. Когда я отправляю, я бы хотел обновить, создать или уничтожить book_award модель. Если флажок установлен, я хотел бы обновить существующую модель или создать новую, если она не существует. Если флажок не установлен, то я хотел бы уничтожить существующую модель или ничего не делать, если награда никогда не существовала. У меня есть частичное book_awards, Я не уверен, должен ли переключатель выбора флажка быть в этом частичном или нет.

Я думаю, что мой флажок будет моим крючком для :_destroy но с его полярностью наоборот. Я думаю, что-то подобное в основном сделает это:

= f.check_box :_destroy, {}, 0, 1

В настоящее время у меня есть это в моем частичном, но я не уверен, где это действительно принадлежит.

Далее следует мой взгляд, который в настоящее время не работает, но, возможно, это поможет продемонстрировать, что я пытаюсь сделать. Я перебираю awards и использовать fields_for установить вложенные атрибуты для всего, что уже существует. Это ужасно уродливо, но я думаю, что это работает. Тем не менее, я не знаю, как начать с другим делом.

= f.label :awards
- @awards.each do |a|
  - if f.object.awards && f.object.awards.include?(a)
    = f.fields_for :book_awards, f.object.book_award.select{|bas| bas.award == a } do |ba|
      = render 'book_awards', :f => ba, :a => a
  - else
    = fields_for :book_awards do |ba|
      = render 'book_awards', :f => ba, :a => a

Я бы предпочел, чтобы награды были перечислены в том же порядке каждый раз (мой @awards назначение в контроллере, вероятно, будет указывать порядок), а не перечисление существующих наград первым или последним.

1 ответ

Решение

Ненавижу отвечать на свой вопрос, но я наконец-то понял, что работает. Первое, что мне нужно было сделать, это обновить "новый" корпус на основе сумасшедшего объекта, который был включен в Railscast. Далее мне нужно было вручную установить :child_index, Наконец, мне нужно было вручную установить :_destroy установите флажок соответственно.

.field
  = f.label :awards
  - @awards.each_with_index do |a,i|
    - if exists = (f.object.awards && f.object.awards.include?(a))
      - new_ba = f.object.book_awards.select{|s| s.award == a}
    - else
      - new_ba = f.object.class.reflect_on_association(:book_awards).klass.new
    = f.fields_for :book_awards, new_ba, :child_index => i do |ba|
      = render 'book_awards', :f => ba, :a => a, :existing => exists

Мой частичный выглядит так:

.field
  = f.check_box :_destroy, {:checked => existing}, 0, 1
  = f.label a.name
  = f.hidden_field :award_id, :value => a.id
  = f.label :year
  = f.number_field :year

Это не очень красиво, но, кажется, делает именно то, что я хотел.

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