Rails 3: nested_form, collection_select, accepts_nested_attributes_for и fields_for - PullRequest
6 голосов
/ 07 июня 2011

Обновление: здесь ответили .

Есть много хороших вопросов и ответов здесь и на веб-сайте о том, как заставить nested_form, collection_select, accepts_nested_attributes_for и fields_for хорошо играть вместе, но я все еще в тупике.Спасибо заранее, если вы можете мне помочь.

Цель: создать новую запись isbn.Isbn может иметь много участников.Я успешно использую ryanb nested_form gem для динамического создания новых полей участника в форме, как требуется.В одном из этих полей используется раскрывающийся список collection_select всех записей имен в Contributor.Когда создается новая запись, многие идентификаторы участников должны быть записаны в таблицу соединений (contributors_isbns).

У меня есть кусочки этой работы, но только до такой степени, что я могу сохранить один идентификатор участника.к новой записи в таблице isbns.Кажется, я нигде не могу записать какие-либо данные в таблицу соединений.

У меня три модели.Участники и Isbns имеют отношения многие ко многим, что я сделал с помощью has_many: through.У isbn может быть много участников, а у участника может быть много isbns.Они присоединяются через contributors_isbn.

isbn.rb

  attr_accessible               :contributor_id
  has_many                      :contributors, :through => :contributors_isbns
  has_many                      :contributors_isbns
  accepts_nested_attributes_for :contributors
  accepts_nested_attributes_for :contributors_isbns

contributor.rb

  attr_accessible               :isbn_id
  has_many                      :contributors_isbns
  has_many                      :isbns, :through => :contributors_isbns
  accepts_nested_attributes_for :isbns

contributors_isbn.rb

  class ContributorsIsbn
  attr_accessible               :isbn_id, :contributor_id
  belongs_to                    :isbn
  belongs_to                    :contributor
  accepts_nested_attributes_for :contributors

В контроллере isbns:

 def new
    @isbn  = Isbn.new
    @title = "Create new ISBN"
    1.times {@isbn.contributors.build}
    @isbn.contributors_isbns.build.build_contributor
  end

(очевидно, я не могу решить, какой метод сборки использовать.)

В представлении isbns new.html.erb:

<%= nested_form_for @isbn, :validate => false do |f| %>
<h1>Create new ISBN</h1>
<%= render 'shared/error_messages', :object => f.object %>
<%= render 'fields', :f => f %>
  <div class="actions">
    <%= f.submit "Create" %>
  </div>  

<% end %>

Вчастичное _fields, версия с очень простым текстовым полем:

<%= field_set_tag 'Contributor' do %>
<%= f.link_to_add "Add Additional Contributor", :contributors %>
<li>
<%= f.label 'Contributor Sequence Number' %>
<%= f.text_field :descriptivedetail_contributor_sequencenumber%>
</li>

<%= f.fields_for :contributors_isbns, :validate => false do |contrib| %>
<li>
<%= contrib.label :id, 'contributors_isbns id' %>
<%= contrib.text_field :id %>
</li>
<% end %>

<li>
<%= f.label 'Contributor Role' %>
<%= f.text_field :descriptivedetail_contributor_contributorrole  %>
</li>

<% end %>

И вот, более причудливая версия, которая тоже не работает:

<%= f.fields_for :contributors_isbns, :validate => false do |contributors| %>
<li>
<%= f.label :personnameinverted, 'Contributor Name' %>
<%= f.collection_select(:contributor_id,  Contributor.all, :id, :personnameinverted ) %>
</li>
<% end %>

Этот код использует ответ от здесь .И то и другое приводит к ошибке «Отсутствует блок» в строке nested_form_for @isbn.

Заранее большое спасибо.

Обновление: здесь - некоторая информация о nested_formдрагоценный камень, который может пригодиться для рассмотрения этой проблемы. А вот [2009, но все еще актуальный пост] [4] на acceptpts_nested_attributes_for.

Обновление 2: ну, вот что. Я ткнулвокруг в урезанной версии этого в двух разных моделях, не используя collection_select или has_many, а просто на простой ассоциации own_to / has_many. Родительская модель - Contract, а дочерняя модель - Istc. Я даже не смог создатьзапись через вложенную форму. Однако, посмотрев в стек и погуглив сообщение об ошибке «Предупреждение.Невозможно массово назначить защищенные атрибуты "Я только что добавил :istcs_attributes в мою строку :attr_accessible и теперь могу добавлять записи. Отсутствует довольно важный бит и случай RTFM, как это прямо в файле readme для gemПозже я обновлю, чтобы увидеть, работает ли это с более сложным has_many посредством ассоциации.

Обновление 4: [Здесь] [5] - еще один полезный пост о том, как бороться с сообщением об ошибке с нулевой записью.

Обновление 5: Небольшой обход - Когда я динамически добавлял в форму новый набор полей, была создана одна из дочерних записей. Дух - у меня была ссылка «Добавить» в области дочерних форм.до:

<%= f.fields_for :istcs do |istc_form| %>
<h4> Istc</h4>
<%= istc_form.label "istc name" %>
<%= istc_form.text_field :title_title_text %>
<%= istc_form.link_to_remove "[-] Remove this istc"%>
<%= f.link_to_add "[+] Add an istc", :istcs  %>
<% end %>

и вот после:

<%= f.fields_for :istcs do |istc_form| %>
<h4> Istc</h4>
<%= istc_form.label "istc name" %>
<%= istc_form.text_field :title_title_text %>
<%= istc_form.link_to_remove "[-] Remove this istc"%>
<% end %>
<%= f.link_to_add "[+] Add an istc", :istcs  %>

Обновление 6, пост-ответ:

О, нет. Набор collection_select не работает.добавление новых записей участников, без использования существующей из модели участников. Кто-то еще тоже имел эту проблему. Есть идеи?

1 Ответ

3 голосов
/ 08 июня 2011

ура! Вот код, который делает всю эту работу. Немного многословно, но не хотел ничего упускать. Мои основные уроки:

  • вам нужно сделать дочерние атрибуты attr_accessible в родительской модели

  • вам нужно сделать родительские и дочерние идентификаторы attr_accessible в модели таблицы соединений

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

contributor.rb модель

class Contributor < ActiveRecord::Base
  attr_accessible  #nothing relevant 
  has_many :contributors_isbns
  has_many :isbns, :through => :contributors_isbns

isbn.rb модель

class Isbn < ActiveRecord::Base
  attr_accessible :contributors_attributes, :contributor_id, :istc_id #etc
  belongs_to  :istc
  has_many   :contributors, :through => :contributors_isbns
  has_many   :contributors_isbns
  accepts_nested_attributes_for :contributors #if you omit this you get a missing block error

contributors_isbn модель

class ContributorsIsbn < ActiveRecord::Base
  belongs_to :isbn
  belongs_to :contributor
  attr_accessible :isbn_id, :contributor_id

контроллер isbn

 def new
    @isbn  = Isbn.new
    @title = "Create new ISBN"
    1.times {@isbn.contributors.build}
  end

new.html.erb

<td class="main">
<%= nested_form_for @isbn, :validate => false do |f| %>
<h1>Create new ISBN</h1>
<%= render 'shared/error_messages', :object => f.object %>
<%= render 'fields', :f => f %>
  <div class="actions">
    <%= f.submit "Create" %>
  </div>  

<% end %>

_fields.html.erb

<%= field_set_tag 'Identifier Details' do %>

<li>
<%= f.label 'Title prefix' %>
<%= f.text_field :descriptivedetail_titledetail_titleelement_titleprefix %>
</li>
<li>
<%= f.label 'Title without prefix' %>
<%= f.text_field :descriptivedetail_titledetail_titleelement_titlewithoutprefix %>
</li>
<li>
<%= f.label 'ISTC' %>
<%= f.collection_select(:istc_id, Istc.all, :id, :title_title_text, :prompt => true) %>
</li>

<% end %>


<%= field_set_tag 'Contributor' do %>
<li>
<%= f.label 'Contributor Sequence Number' %>
<%= f.text_field :descriptivedetail_contributor_sequencenumber%>
</li>

<%= f.fields_for :contributors, :validate => false do |contributor_form| %>
<li>
<%= contributor_form.label :personnameinverted, 'Contributor Name' %>
<%= contributor_form.collection_select(:isbn_id, Contributor.all, :id, :personnameinverted ) %>
</li>
<%= contributor_form.link_to_remove "[-] Remove this contributor"%>
<% end %>
<%= f.link_to_add "[+] Add a contributor", :contributors  %>


<li>
<%= f.label 'Contributor Role' %>
<%= f.text_field :descriptivedetail_contributor_contributorrole  %>
</li>

<% end %>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...