2

Cette question concerne le nettoyage de la vue et le travail du contrôleur.Comment rendre la vue plus simple, le contrôleur plus utile?

J'ai de nombreux cas dans mon projet où j'ai des variables imbriquées affichées dans ma vue. Par exemple:

# controller 
@customers = Customer.find_all_by_active(true) 
render :layout => 'forms' 

# view 
<% @customers.each do |c| %> 
    <%= c.name %> 
    <% @orders = c.orders %> # I often end up defining nested variables inside the view 
    <% @orders.each do |o| %> 
    ... 
    <% end %> 
<% end %> 

Je suis assez nouveau pour RoR, mais il semble que ce que je fais ici est en contradiction avec la mentalité de «contrôleur intelligent, vue muet. Où j'ai beaucoup de clients, chacun avec beaucoup de commandes, comment puis-je définir ces variables correctement dans mon contrôleur et puis les accéder à l'intérieur de la vue?

Si vous pouviez donner un exemple de la façon dont le contrôleur regarderait et comment je serais lié à cela dans la vue, ce serait incroyablement utile. Merci beaucoup!

Répondre

2

Je ne pense pas qu'il y ait quelque chose de radicalement faux avec ce que vous faites. Faire une boucle entre les clients et sortir certains de leurs attributs et pour chaque client, boucler leurs ordres et produire certains attributs est une opération très orientée sur la vue.

Dans l'architecture MVC, le contrôleur a la responsabilité d'interagir avec le modèle, en sélectionnant la vue et (certainement dans le cas de Rails) fournissant à la vue les informations dont il a besoin pour rendre le modèle.

Vous pourriez envisager d'extraire le code dans un assistant d'affichage, si vous avez ce code exact répété plus d'une fois. Vous pourriez même le généraliser en passant au nom d'un modèle et d'une association. Je ne l'ai pas testé, mais vous devriez être en mesure de faire quelque chose comme ceci:

def display_attributes(models, association, attribute, association_attribute) 
    content = '' 
    models.each do |m| 
    content << "<p>#{m.attribute}</p>" 
    associated_models = m.association 
    associated_models.each do |am| 
     content << "<p>#{am.association_attribute}</p>" 
    end 
    end 
    content 
end 

Puis dans la vue, vous pouvez utiliser l'aide comme ceci:

<%= display_attributes(@customers, orders, name, name) %> 

Il est évident que vous changeriez la Balise HTML dans la méthode d'assistance pour répondre à vos besoins. Notez que si vous n'utilisez pas Rails 3, vous souhaiterez échapper la sortie des noms d'attribut dans la méthode helper.

+0

Merci pour l'idée d'aide à la vue. A quoi ressemblerait le code dans l'assistant + voir si je veux le rendre générique? Je vous remercie! – sscirrus

+0

@sscirrus J'ai modifié ma réponse. –

2

Je ne pense pas qu'il y ait quelque chose de mal avec votre code. Je voudrais simplement suggérer pour vous d'utiliser un :include dans votre découverte

@customers = Customer.find_all_by_active(true, :include => :orders) 

pour réduire le nombre de requêtes.

+0

@j: Je peux certainement utiliser un: include. Dois-je faire quelque chose pour réduire mes requêtes ou sont-elles automatiquement réduites? – sscirrus

+0

Non, vous n'avez besoin de rien d'autre. Avec l'option ': include', les requêtes seront * automatiquement * réduites car elles seront chargées avec impatience. Vous pouvez lire ici sur le chargement désireux: http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html:] –

+0

Merci J, vous avez marqué +1 =) – sscirrus

0

Je ne vois rien de mal avec le code que vous avez montré. Vous êtes mélangé à propos de l'approche "contrôleur intelligent, vue stupide", j'ai tendance à préférer le "skinny controller, fat model", donc en effet la vue devrait être bête, mais vous mettez l'intelligence à l'intérieur de votre modèle, et vos aides (ou utilisation un présentateur), mais certainement pas dans le contrôleur.