Update: answered here

在这里和互联网上,有很多很好的问题和答案,它们可以使nested_form,collection_select,accepts_nested_attributes_for和fields_for一起很好地玩耍,但我仍然感到困惑。在此先感谢您的帮助。

目的:生成一个新的isbn记录。一个isbn可以有很多贡献者。我已成功使用ryanb nested_form gem根据需要在表单上动态产生新的贡献者字段。这些字段之一使用Contributor中所有名称记录的collection_select下拉列表。创建新记录时,需要将许多参与者ID写入联接表(contributors_isbns)。

我已经做了一些工作,但是到了可以将单个贡献者ID保存到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


贡献者

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


贡献者_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部分中,具有非常简单的text_field的版本:

<%= 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 %>


此代码使用来自here的答案。两者均在nested_form_for @isbn行上导致“缺少块”错误。

再次非常感谢。

更新:here是有关nested_form gem的一些信息,对于解决此类问题可能会派上用场。这是accepts_nested_attributes_for上的[2009但仍然相关的文章] [4]。

更新2:好,这是一件事情。我一直在两个不同的模型中使用它的简化版本,而不是通过collection_select或has_many来使用,而只是在一个简单的Emirates_to / has_many关联上。父模型是Contract,子模型是Istc。我什至无法通过嵌套表单创建记录。但是,在查看堆栈并搜索错误消息“警告。无法批量分配受保护的属性”之后,我刚刚在:istcs_attributes行中添加了:attr_accessible,现在可以添加记录了。相当重要的一点缺失,还有RTFM的情况,因为它就在gem自述文件中。稍后我将进行更新,以查看是否可以通过关联在更复杂的has_many上使用。

更新4:[此处] [5]是有关如何处理nil记录错误消息的另一篇有用的文章。

更新5:略微绕行-当我向表单动态添加一组新字段时,正在创建一个子记录。 h-我在子表单区域内拥有“添加”链接。这是之前的内容:

<%= 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不起作用。它正在添加新的贡献者记录,而不使用贡献者模型中的现有记录。 Someone else也有这个问题。有任何想法吗?

最佳答案

晕!这是使所有这些工作有效的代码。有点冗长,但不想遗漏任何内容。我的主要知识:


您需要在父模型中使子属性attr_accessible
您需要在联接表模型中使父级和子级id 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


贡献者_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 %>

08-18 12:52