LeRiton | On va faire simple, je vais poster plein de code. Je me lance aujourd'hui dans l'analogie Weight Watcher \o/
Mettons que mes utilisateurs puissent entrer des repas, des shoots de dope qui fait maigrir et des commentaires. L'idée est de pouvoir retrouver, à partir de l'une des entrée, ce que l'utilisateur a fait autour (je brode mon histoire en live, c'est un vrai bonheur).
Genre Monique, 43 ans, a entré un repas à 700 g de graisses (valeur entière) le 06/06/2006 à 12h40, avec quelques heures après une injection de SlimDope © de 0.85 unités (valeur flottante). Dans l'après-midi, elle à faire 1 heure de sport (en fait non, mais elle entre quand même la donnée pour se donner bonne conscience, elle doit croire que l'admin du site surveille et juge ses inscrits, enfin bref), elle entre donc le commentaire "je suis contente, j'ai fait 1 heure de sport" (un string donc).
L'ensemble de ces différentes entrées est accompagnée d'un datetime, car un utilisateur peut entrer une action qui s'est déroulée dans le passé (donc pas d'exploitation possible des champs created_at et updated_at dans ce cas).
Les modèles ressemble à ça :
Code :
class User < ActiveRecord::Base has_many :meals has_many :dopes has_many :comments end
|
Code :
class Meal < ActiveRecord::Base belongs_to :user validates_presence_of :lipids, :datetime alias_attribute :value, :lipids end
|
Code :
class Dope < ActiveRecord::Base belongs_to :user validates_presence_of :units, :datetime alias_attribute :value, :units end
|
Code :
class Comment < ActiveRecord::Base belongs_to :user validates_presence_of :text, :datetime alias_attribute :value, :text end
|
Les alias_attribute sont là comme ébauche de début de tentative d'unification de l'ensemble. Ça, c'est pour le côté modèle. Je pourrais effectivement garder les trois, ça me pose pas de soucis. En fait, la question de factorisation s'est posée parce que cette structure (qui ne me dérange pas dans le modèle) occasionne pas mal de duplication dans les autres couches.
Prenons maintenant l'exemple de l'écran de contrôle Weight Watcher d'un utilisateur, qui regroupe dans une page générale ses infos perso, ainsi que les dernières entrées (des 3 types précédents) et la possibilités d'en ajouter un rapidement. En gros, sur la même page, 3 div (repas, dopes et commentaires) avec les 3 derniers items pour chaque et un formulaire d'ajout. Du point de vue de la vue donc (...), rappelons que le bouzin est internationalisé (même si je sens que c'est premature optimization et que ça va partir à la trappe dans pas longtemps, prenons le cas quand même).
Si je ne factorise pas, je me retrouve avec :
Pour les repas :
Code :
<div id="meals"> <h2><%= t(:meals_title) %></h2> <% unless @last_meals.empty? %> <div class="last_values"> <h3><%= t(:last_meals_title) %></h3> <% @last_meals.each do |meal| %> <p> <%= meal.value.to_s + " #{t(:meal_unit)}, " + l(meal.datetime, :format => :custom).downcase %> <%= button_to "Delete", user_meal_path(@user, meal), :method => :delete %> </p> <% end %> </div> <% end %> <% form_for [@user, @new_meal] do |f| %> <fieldset><legend><%= t(new_meal_title) %></legend> <p><%= f.label :value, t(meal_value_label) %> <%= f.text_field :value, :size => 3 %><%= " #{t(meal_unit)}" %></p> <p><%= f.label :datetime, t(:datetime_label) %> <span id="<%= datetime_id %>"><%= f.datetime_select :datetime %></span></p> <%= submit_tag t(:add_button_label) %> </fieldset> <% end %> </div>
|
Et les deux même partiels pour les dopes et commentaires. En faisant un partiel commun avec passage de paramètres (voir mon premier post, l'appel du partiel "user_entry" correspond au code précédent factorisé pour les 3 types), je me retrouve avec une tapée d'arguments, et je trouve ça moche.
Enfin viens la couche controleur. J'ai regardé tes liens, ça semble être une bonne piste pour mon problème, même si je crains effectivement que le cas particulier (qui arrive toujours un jour ou l'autre, le fourbe) vienne compliquer les choses.
Merci de t'attarder sur mes questions en tout cas. Je suis assez pour l'utilisation de blabla, mais dans le cas où je dois pondre un roman d'explications, je préfère quand même garder ça dans un thread séparé (ne serait-ce que si quelqu'un rencontre le soucis un jour).
|