2009-11-20 65 views
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 -%> 

回答

1

你是正確的使用fields_for,但它會使它裏面有什麼每個employment,所以從render :partial刪除:collection參數。相反,通過把這個在您的Account模型使用嵌套形式:

accepts_nested_attributes_for :employments 

閱讀更多關於嵌套形式在這裏:http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

+0

我已經在那裏使用了'accep_nested_attributes_for',對不起,我忘了將它包含在我的例子中。但是,當我刪除':collection'參數時,它會嘗試評估部分中的'nil.person'。 – 2009-11-20 17:26:28

+0

當你不使用部分時它會工作嗎?只需在'fields_for'中嵌入嵌套字段? – Ben 2009-11-20 18:15:37

+0

我只想顯示現有的工作記錄,只有某些字段可編輯,特別是刪除字段。是否可以在'field_for'內將字段顯示爲純HTML?我正在使用'render:partial',因爲這給了我每個記錄的局部變量。 – 2009-11-20 18:29:24

3

它呈現的是部分在就業模型中的每個領域 - 當你真的需要爲每個就業記錄做一次。也就是說,除去遍歷所有fields_for:

<% form_for @account do |f| -%> 
    <%= render :partial => 'employment', :collection => @account.employments %> 
<% end -%> 
+0

fields_for是一個迭代器?我雖然只是改變了表單構建器的名稱代。 – 2009-11-20 01:04:36