lundi 22 janvier 2007
Rails : with_scope :find => {} do
Par Christophe, lundi 22 janvier 2007 à 22:58 :: Développement
Je tenais à poster sur une méthode méconnue de ActiveRecord nommée with_scope
Imaginez :
Dans notre site, qui contient des articles modérés qui appartiennent à des auteurs, nous faisons souvent appel (dans nos controllers) à une sélection des articles validés, avec différentes conditions impliquées. Par exemple :
Article.find(params[:id], :conditions => 'statut = 1') # ou encore, pour vérifier si l'article (validé) appartient bien un auteur Article.find(params[:id], :conditions => ['statut = 1 and auteur_id = ?', params[:auteur]])
C'est dans ces conditions que with_scope va nous sauver de ces nombreuses répétitions, qui enfreignent le motto DRY. Dans le model de l'article, nous rajoutons ceci :
def self.find_active(*args)
with_scope :find => { :conditions => 'statut = 1'} do
find(*args)
end
end
Ainsi, vous pouvez désormais utiliser :
Article.find_active(params[:id])
Ce qui fait que with_scope est plus puissant qu'un simple merge d'arrays (d'arguments ou d'hashs (de conditions), c'est qu'il permet de fusionner vraiment les conditions. Donc, nous pouvons faire ce genre choses :
Article.find_active(params[:id], :conditions => ['categorie_id = ?', params[:categorie]])
... ce qui fusionnera les conditions 'statut = 1' et ['categorie_id = ?', params[:categorie]] bien comme il faut.
MAIS.
Oui, il y a un mais. En fait, on peut faire mieux que le dernier exemple, surtout si vous ne faites pas ce genre de choses conditions souvent (plus de 3 fois) :
Article.find_by_id_and_categorie_id_and_statut(params[:id], params[:categorie], 1)
Ici, se trouve la puissance des "dynamics finders" ActiveRecord, qui permettent de chercher en impliquant directement le nom des champs dans le nom de la méthode, ce qui a le mérite d'être clair et facile à comprendre, tout en restant souple. Autre exemple pour les yeux :
Person.find_all_by_island_and_type_and_genre_and_sexy('Guadeloupe', 'girl', 'open minded', true)
:-)
Notez enfin la différence notable (wow, "noter la différence notable" ...) entre find_by qui retourne un seul résultat et find_all_by qui retourne un array de résultats.
:: 7 commentaires ::
