【问题标题】:Rails 3: nested_form, collection_select, accepts_nested_attributes_for and fields_forRails 3:nested_form、collection_select、accepts_nested_attributes_for 和 fields_for
【发布时间】:2011-06-07 19:11:21
【问题描述】:

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 可以有多个贡献者,一个贡献者可以有多个 isbn。他们通过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

贡献者.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 部分中,有一个非常普通的 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 的一些信息,对于查看此类问题可能会派上用场。这是关于accept_nested_attributes_for 的[2009 年但仍然相关的帖子][4]。

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

更新 4:[这里][5] 是另一个有用的帖子,介绍如何处理零记录错误消息。

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

<%= 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 也有这个问题。有任何想法吗?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 fields-for nested-form-for


    【解决方案1】:

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

    • 你需要让父模型中的子属性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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多