2009-11-20 1 views
1

Compte tenu de ces relations:Pourquoi est ce rendu: ligne partielle en répétant deux fois ma collection?

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 

J'essaie d'énumérer les dossiers d'emploi pour un compte:

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

J'ai vérifié que le tableau de l'emploi dans @account contient deux dossiers, mais je obtenir quatre copies du partiel parce qu'il itère des emplois deux fois:

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) 

Quelqu'un peut-il expliquer pourquoi cela se produirait?


Voici quelques informations supplémentaires:

La _employment.html.erb partielle:

<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 est le seul endroit où je besoin de générer un champ de formulaire à. Il crée le champ _delete pour l'enregistrement et connecte un lien de suppression qui modifie la valeur à '1'. La propriété 'role' peut également être modifiable, cependant. L'important est que je ne veux pas que tous les champs soient modifiables.

Les actions accounts_controller pour ce point de vue:

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 

Ben m'a obtenu d'aller dans la bonne direction. Certaines inspections d'exécution révèlent que l'enregistrement est stocké dans la variable object (que je connaissais déjà, mais dans un contexte différent). Je peux donc réécrire la clause fields_for comme:

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

Répondre

1

Vous avez raison d'utiliser fields_for, mais il va rendre ce qui est à l'intérieur de celui-ci pour chaque employment, donc supprimer le paramètre :collection de render :partial. Au lieu de cela, utilisez les formulaires imbriqués en mettant dans votre modèle de compte:

accepts_nested_attributes_for :employments 

en savoir plus sur les formes imbriquées ici: http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

+0

J'utilise déjà 'accept_nested_attributes_for' là-dedans, désolé j'ai oublié de l'inclure dans mon exemple. Mais quand je supprime le paramètre ': collection', il essaie d'évaluer' nil.person' dans le partial. –

+0

Est-ce que cela fonctionne quand vous n'utilisez pas un partiel? Coller simplement les champs imbriqués dans 'fields_for'? – Ben

+0

Plutôt que de simplement créer des champs, je souhaite afficher les enregistrements d'emploi existants avec uniquement certains champs modifiables, en particulier le champ de suppression. Est-il possible d'afficher les champs en tant que html dans 'field_for'? J'utilisais 'render: partial' parce que cela me donnait une variable locale pour chaque enregistrement. –

3

Son rendu que partielle pour chaque champ dans le modèle emplois - quand vraiment vous voulez faire une fois pour chaque enregistrement de l'emploi. Enlver l'itération sur la fields_for:

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

fields_for est un itérateur? Je pense que cela change simplement la génération du nom du générateur de formulaire. –

Questions connexes