1

鉴于这些关系:

class Account < ActiveRecord::Base
  has_many :employments
  has_many :people, :through => :employments
  accepts_nested_attributes_for :employments
end

class Employment < ActiveRecord::Base
  belongs_to :account
  belongs_To :person
end

我正在尝试列出一个帐户的就业记录:

<% form_for @account do |f| -%>
  <% f.fields_for :employments do |e| -%>
    <%= render :partial => 'employment', :collection => @account.employments, :locals => { :f => e } %>
  <% end -%>
<% end -%>  

我已经验证了 @account 中的就业表包含两条记录,但我得到了部分的四个副本,因为它重复了两次就业:

Employment Load (1.0ms)   SELECT * FROM [employments] WHERE ([employments].account_id = 1) 
Person Load (1.3ms)   SELECT * FROM [people] WHERE ([people].[id] = 2) 
Rendered accounts/_employment (17.9ms)
Person Load (1.5ms)   SELECT * FROM [people] WHERE ([people].[id] = 1) 
Rendered accounts/_employment (5.1ms)
Rendered accounts/_employment (2.2ms)
Rendered accounts/_employment (2.1ms)

谁能解释为什么会发生这种情况?


以下是一些附加信息:

_employment.html.erb部分:

<div class="employment">
  <span class="name"><%= link_to h(employment.person.name), person_path(employment.person) %></span>
  <span class="role"><%=h employment.role %></span>
  <span class="commands"><%= remove_child_link "Remove", f %></span>
</div>

remove_child_link是我唯一需要生成表单域的地方。它为记录创建_delete字段并连接一个将值更改为“1”的删除链接。不过,“角色”属性也可以是可编辑的。重要的是我不希望所有字段都是可编辑的。

此视图的accounts_controller操作:

def edit
  @account = Account.find(params[:id])
end

def update
  @account = Account.find(params[:id])

  respond_to do |format|
    if @account.update_attributes(params[:account])
      flash[:notice] = "#{@account.business_name} was successfully updated."
      format.html { redirect_to @account }
    else
      format.html { render :action => "edit" }
    end
  end
end

本让我朝着正确的方向前进。一些运行时检查显示记录存储在object变量中(我已经知道,但在不同的上下文中)。所以我可以将fields_for子句重写为:

<% form_for @account do |f| -%>
  <% f.fields_for :employments do |e| -%>
    <div class="employment">
      <span class="name"><%= link_to h(e.object.person.name), person_path(e.object.person) %></span>
      <span class="role"><%=h e.object.role %></span>
      <span class="commands"><%= remove_child_link "Remove", e %></span>
    </div>
  <% end -%>
<% end -%>
4

2 回答 2

3

它为就业模型中的每个字段呈现部分内容 - 当您真的想为每个就业记录执行一次时。也就是说,删除 fields_for 上的迭代:

<% form_for @account do |f| -%>
   <%= render :partial => 'employment', :collection => @account.employments %>
<% end -%>
于 2009-11-20T01:00:12.537 回答
1

你使用是正确的fields_for,但它会为每个渲染它里面的东西employment,所以:collectionrender :partial. 相反,通过将其放入您的 Account 模型中来使用嵌套表单:

accepts_nested_attributes_for :employments

在此处阅读有关嵌套表单的更多信息:http ://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

于 2009-11-20T02:43:16.433 回答