Skinny controllers and fat models 1

Publié par Yannick Francois Mar 21 avr 2009 08:18:00 GMT

Hier, j’ai posé une question à la terre entière (ou presque):

http://identi.ca/notice/3568719

MyModel.paginate(blablabla) or just call MyModel.give_data and call paginate in MyModel ?

J’ai mis en place une pagination sur une liste de commande. Cela à plusieurs avantages.

  • Graphique d’abord. On ne peut vraiment pas proposer une interface claire avec une liste de 150 commandes
  • Performances ensuite. Aller cherche 150 commandes d’un coup, c’est faire attendre le client qui finalement n’en fera que 10.

Ceci étant dit, sur divers exemple que j’ai observé à droite et à gauche, l’appel au modèle pour récupérer la liste de commandes dans le contrôleur ce fait sous la forme:

  @ma_liste = MonModel.paginate :page => params[:page], :per_page => 10, :condition {mes_conditions}, :order => 'date DESC'

Je ne détail pas les conditions ici, mais pourtant ce sont elles qui me gène dans ce code. L’appel à paginate (ou une autre méthode) dans le contrôleur ne me gène pas, de toute façon, il faut bien qu’il travail un peu, même s’il est maigre ! Mais par contre j’ai beaucoup de mal avec le fait que le contrôleur connaisse les conditions pour la récupération de la liste. D’autant que j’ai dans ces conditions quelque valeur par défaut qui dépende d’un contexte non présent dans les paramètres aujourd’hui.

Je vais donc opter pour le déplacement de l’appel à paginate dans mon modèle. J’ai donc maintenant dans mon contrôleur quelque chose de plus clair, et plus simple (ou plus maigre :)):

  @ma_liste = MonModel.commandes_en_attente params

Et dans mon model

  def commande_en_attente params
    MonModel.paginate :page => params[:page], :per_page => 10, :condition {mes_conditions}, :order => 'date DESC'
  end

C’est bien beau, mais je me retrouve maintenant avec des éléments de présentation dans mon modèle. C’est mal.

Je vais pour l’instant passer la page demandé et la quantité par page en paramètre.

class MonController < ApplicationController
  def index
    @ma_liste = MonModel.commandes_en_attente params[:page], 2 
  end
end

class Commande < ActiveRecord::base
  def commande_en_attente params page, perpage
    MonModel.paginate :page => page, :per_page => perpage, :condition {mes_conditions}, :order => 'date DESC'
  end
end

Ce n’est pas top non plus, mais je préfère cela pour l’instant. Si quelqu’un a une idée, je suis prêt à l’entendre.

  1. Avatar
    Bruno Michel about 4 hours plus tard:

    J’aurais tendance à faire ça avec un named_scope :

    class MonController < ApplicationController def index @ma_liste = Commande.en_attente.paginate :page => params[:page], :per_page => 2 end end class Commande named_scope :en_attente, :conditions => { mes_conditions } end