web-dev-qa-db-fra.com

Rails: les partiels devraient-ils connaître les variables d'instance?

Par exemple, nifty_scaffolding de Ryan Bates le fait

edit.html.erb

<%= render :partial => 'form' %>

new.html.erb

<%= render :partial => 'form' %>

_form.html.erb

<%= form_for @some_object_defined_in_action %>

Cet état caché me met mal à l'aise, donc j'aime généralement le faire

edit.html.erb

<%= render :partial => 'form', :locals => { :object => @my_object } %>

_form.html.erb

<%= form_for object %>

Alors, quoi de mieux: a) avoir des variables d'instances d'accès partielles ou b) passer une partielle toutes les variables dont il a besoin?

J'ai opté pour b) récemment, mais je suis tombé sur un petit cornichon:

some_action.html.erb

<% @dad.sons.each do |a_son| %>
<%= render :partial => 'partial', :locals => { :son => a_son } %>
<% end %>

_partial.html.erb

The son's name is <%= son.name %>
The dad's name is <%= son.dad.name %>

son.dad fait un appel à la base de données pour aller chercher le père! Donc, je devrais soit accéder à @dad, ce qui reviendrait à a) avoir des variables d'instance d'accès partielles soit je devrais passer @dad dans les sections locales, en changeant render: partial en <% = render : partial => 'partial',: locals => {: dad => @dad,: son => a_son}%>, et pour une raison quelconque, passer un tas de vars à mon partial me met mal à l'aise. Peut-être que d'autres le ressentent également.

J'espère que cela avait du sens. Vous cherchez un aperçu de tout cela ... Merci!

63
Alexandre

Dans les versions récentes de Rails il est un peu plus facile de rendre des partiels et de leur passer des locaux. Au lieu de cela.

<%= render :partial => 'form', :locals => { :item => @item } %>

Tu peux le faire.

<%= render 'form', :item => @item %>

Je ne fais pas cela dans le générateur Nifty Scaffold pour garder la compatibilité descendante, mais je changerai cela dans une prochaine version.

Quant à savoir s'il est acceptable d'utiliser des variables d'instance dans les partiels. Je pense que c'est. En pratique, quel est l'inconvénient? Certes, les choses peuvent devenir incontrôlables si vous n'êtes pas cohérent, mais j'aime appliquer ces directives.

  1. Ne créez jamais une variable d'instance juste pour la partager entre des partiels. Cela signifie généralement que vous ne partagerez que l'objet ressource du contrôleur.

  2. Si le partiel est du même nom que la ressource, passez-le en tant que local avec <%= render @item %>.

  3. Si le partiel sera partagé entre plusieurs contrôleurs, n'utilisez que des locaux.

C'est ce qui fonctionne bien pour moi de toute façon.

Astuce bonus: si vous vous retrouvez à passer beaucoup de locaux dans un partiel et que vous voulez que certains d'entre eux soient facultatifs, créez une méthode d'aide qui rend le partiel. Ensuite, passez toujours par la méthode d'assistance afin de pouvoir créer une interface propre avec des arguments facultatifs pour le rendu du partiel.

103
ryanb

L'utilisation de @instance_variables dans les partiels est une mauvaise conception.

L'utilisation de la variable d'instance dans les partiels fonctionne, mais il peut être plus difficile de maintenir les applications si des modifications sont nécessaires.

L'inconvénient de l'utilisation de variables d'instance dans les partiels est que vous créez une dépendance dans le partiel à quelque chose en dehors de la portée (couplage) du partiel. Cela rend la partie plus difficile à réutiliser et peut forcer des modifications dans plusieurs parties de l'application lorsque vous souhaitez effectuer une modification dans une partie.

Partiels qui utilisent des variables d'instance:

  • doit changer lorsque la variable d'instance dans n'importe quel contrôleur qui utilise la modification partielle soit le nom de la variable d'instance, soit son type ou sa structure de données
  • faire en sorte que toutes les actions du contrôleur qui utilisent le partiel changent de la même manière en même temps lorsqu'il y a des changements dans l'utilisation de la variable d'instance
  • décourager la réutilisation, car ils ne peuvent être facilement réutilisés que dans des actions qui configurent des variables d'instance avec le même nom et les mêmes données

Au lieu de cela, passez les sections locales aux partiels:

<%= render 'reusable_partial', :item => @item %>

Maintenant, parce que le partiel ne fait référence qu'à item et non @item, l'action qui rend la vue qui rend la partie réutilisable est libre de changer sans affecter la partie réutilisable et les autres actions/vues qui la rendent:

<%= render 'reusable_partial', :item => @other_object.item %>

En outre, cela peut être réutilisé dans des contextes où il n'y a pas de @item:

<%= render 'reusable_partial', :item => @duck %>

Si mon @duck changements à l'avenir et plus de charlatans comme reusable_partial s'attend à ce que (l'interface de l'objet change), je peux aussi utiliser un adaptateur pour passer le type d'élément que reusable_partial attend:

<%= render 'reusable_partial', :item => itemlike_duck(@duck) %>

Toujours?

Il existe de nombreuses situations où vous n'avez probablement pas besoin de partiels découplés comme celui-ci, et il est plus facile à court terme d'utiliser une variable d'instance. Cependant, il est difficile de prédire les besoins futurs de votre application.

En tant que tel, cela permet une bonne pratique générale tout en ayant un coût relativement faible.

42
Edward Anderson

Vous pouvez l'avoir dans les deux sens. Au sommet de votre partiel:

<% item ||= @item %>

De cette façon, il fonctionne avec ou sans passer la variable locale, fournissant une valeur par défaut saine, mais n'empêchant pas une utilisation alternative du partiel.

5
Vezquex

Je vote pour a) pour une raison très précise - SEC! Si vous commencez à passer une variable - comme ça - la prochaine chose que vous savez - c'est un gâchis - disons que vous devez changer la façon dont votre variable est nommée ou quelque chose d'autre à ce sujet - alors vous devez aller à TOUTES vos vues et les changer au lieu d'UN partiel. Aussi - si vous changez votre partiel - disons qu'il produit un tableau avec un certain résultat, il changera sur toutes vos vues, donc vous aurez besoin de savoir quelles vues sont utilisées, un bon IDE devrait être en mesure de vous aider avec cela, mais j'aime aussi avoir une petite section de commentaires en haut de la vue - où je mentionne simplement où il est utilisé et pourquoi - aide un autre programmeur et vous aide à vous souvenir au cas où vous auriez besoin de venir revenir à un partiel et le modifier. Mais le but du partiel est de l'appeler SANS avoir à passer quoi que ce soit de la vue, afin que vous n'ayez pas à modifier tous les endroits d'où le partiel est appelé si cette variable change d'une manière ou d'une autre.

En fin de compte, c'est un choix de conception - et pour être honnête, sauf si vous exécutez un facebook, la recherche supplémentaire que vous faites n'est pas si grave, mais ce n'est tout simplement pas très SEC.

P.S .: Je viens d'y penser - vous pouvez en fait résumer la façon dont vous appelez partiel dans une méthode d'assistance, donc si la façon dont vous appelez votre partiel doit changer - alors vous avez juste besoin de modifier un endroit.

3
konung