Rails 3:nested_form,collection_select,accepts_nested_attributes_for和fields_for

更新:在这里回答 。

这里有很多很好的问题和答案,关于获取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做过:通过。 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视图中:

  false do |f| %> 

Create new ISBN

f.object %> f %>

在_fields partial中,具有非常纯文本字段的版本:

   
  • false do |contrib| %>
  • 在这里,一个不起作用的发烧友版本:

      false do |contributors| %> 
  • 此代码使用此处的答案。 两者都会导致nested_form_for @isbn行出现“Missing block”错误。

    非常感谢您提前。

    更新: 这里有一些关于nested_form gem的信息,它可能会派上用场来查看这类问题。 这里有一个关于accepts_nested_attributes_for的[2009但仍然相关的post] [4]。

    更新2:嗯,这是一件事。 我一直在两个不同的模型中探讨这个版本的缩减,不是使用collection_select或has_many,而只是简单的belongs_to / has_many关联。 父模型是Contract,子模型是Istc。 我甚至无法通过嵌套表单创建记录。 但是,在查看堆栈并搜索错误消息“警告。无法批量分配受保护的属性”后,我刚刚添加:istcs_attributes到my :attr_accessible行,现在我可以添加记录。 一个相当重要的位丢失,以及一个RTFM的案例,因为它就在gem自述文件中。 我稍后会更新,看看这是否适用于更复杂的has_many通过关联。

    更新4:[这里] [5]是关于如何处理nil记录错误消息的另一个有用的post。

    更新5:轻微绕行 – 当我向表单动态添加一组新字段时,正在创建一个子记录。 Duh – 我在子表单区域中有“添加”链接。 这是以前的:

      

    Istc

    这是后面的:

      

    Istc

    更新6,回复后:

    哦,不。 collection_select不起作用。 它正在添加新的贡献者记录,而不是使用贡献者模型中的现有记录。 其他人也有这个问题。 有任何想法吗?

    好哇! 这是使所有这些工作的代码。 有点啰嗦,但不想遗漏任何东西。 我的主要经验是:

    • 您需要在父模型中使子属性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 

    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

      <%= nested_form_for @isbn, :validate => false do |f| %> 

    Create new ISBN

    <%= render 'shared/error_messages', :object => f.object %> <%= render 'fields', :f => f %>
    <%= f.submit "Create" %>
    <% end %>

    _fields.html.erb

     <%= field_set_tag 'Identifier Details' do %> 
  • <%= f.label 'Title prefix' %> <%= f.text_field :descriptivedetail_titledetail_titleelement_titleprefix %>
  • <%= f.label 'Title without prefix' %> <%= f.text_field :descriptivedetail_titledetail_titleelement_titlewithoutprefix %>
  • <%= f.label 'ISTC' %> <%= f.collection_select(:istc_id, Istc.all, :id, :title_title_text, :prompt => true) %>
  • <% end %> <%= field_set_tag 'Contributor' do %>
  • <%= f.label 'Contributor Sequence Number' %> <%= f.text_field :descriptivedetail_contributor_sequencenumber%>
  • <%= f.fields_for :contributors, :validate => false do |contributor_form| %>
  • <%= contributor_form.label :personnameinverted, 'Contributor Name' %> <%= contributor_form.collection_select(:isbn_id, Contributor.all, :id, :personnameinverted ) %>
  • <%= contributor_form.link_to_remove "[-] Remove this contributor"%> <% end %> <%= f.link_to_add "[+] Add a contributor", :contributors %>
  • <%= f.label 'Contributor Role' %> <%= f.text_field :descriptivedetail_contributor_contributorrole %>
  • <% end %>