为什么渲染:部分行迭代我的集合两次?

时间:2009-11-20 00:52:24

标签: ruby-on-rails forms partial-views

考虑到这些关系:

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

2 个答案:

答案 0 :(得分:3)

它为就业模型中的每个字段提供部分 - 当你真的想要为每个就业记录做一次时。也就是说,删除fields_for:

上的迭代
<% form_for @account do |f| -%>
   <%= render :partial => 'employment', :collection => @account.employments %>
<% end -%>

答案 1 :(得分:1)

使用fields_for是正确的,但它会为每个employment呈现其中的内容,因此请从:collection中删除render :partial参数。而是通过将其放入您的帐户模型中来使用嵌套表单:

accepts_nested_attributes_for :employments

在此处详细了解嵌套表单:http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes