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