Modele avec condition systématique


#1

Bonjour à tous,

Tout est dans le titre ou presque. Je voudrais savoir s’il y a moyen de
faire un model avec une condition toujours valable. J’ai une table
“produits” et je ne voudrais voir que les produits “exportés”
quelquesoit la
requête find lancée dans le controller. J’ai d’abord pensé à faire une
vue
avec la condition where qui va bien, mais c’est pas très Rails…

Merci


#2

Le 23 janv. 07 à 15:22, Samuel DECHOMETS a écrit :

Bonjour à tous,

Salut,

Tout est dans le titre ou presque. Je voudrais savoir s’il y a
moyen de faire un model avec une condition toujours valable. J’ai
une table “produits” et je ne voudrais voir que les produits
“exportés” quelquesoit la requête find lancée dans le controller.
J’ai d’abord pensé à faire une vue avec la condition where qui va
bien, mais c’est pas très Rails…

Ton bonheur se trouve dans with_scope :

Product.with_scope :find => { :conditions => [ ‘state = ?’,
‘exported’ ] } do
Product.find(:all)
end

Nicolas C.
http://www.bounga.org
http://www.cavigneaux.net


#3

Le 23/01/07, Nicolas C. removed_email_address@domain.invalid a écrit :

“exportés” quelquesoit la requête find lancée dans le controller.
Nicolas C.
http://www.bounga.org
http://www.cavigneaux.net

Merci Nicolas, mais ce n’est pas exactement ce que je cherche.
D’ailleurs j’ai un peu de mal à voir l’intérêt du with_scope dans cet
exemple par rapport à un Product.find(:all,:conditions=> [ ‘state = ?’,
‘exported’ ]) ?
En fait, j’utilise des lib qui gèrent les find et je ne peux pas
“encapsuler” ces find dans un with_scope à moins de hacker les libs en
questions, ce dont je n’ai pas très envie.
J’aurais préféré un truc du style :

class ProduitExportesController < ApplicationController
model :product, :conditions=> [ ‘state = ?’, ‘exported’ ]
use_ma_lib

end

module ma_lib
self.included(base)
super
base.extend(ClassMethods)
end
module ClassMethods
def use_ma_lib
def foo1
…find(:all)…
end
def foo2
…find(:all)…
end
end
end
end

Avec les find(:all) de ma_lib prenant bien sûr en compte la condition [
‘state = ?’, ‘exported’ ]

J’espère avoir été clair, j’aurais dû apporter plus de précision sur mon
premier post :wink:

Samuel


#4

Le 23 janv. 07 à 17:06, Samuel DECHOMETS a écrit :

moyen de faire un model avec une condition toujours valable. J’ai
end
“encapsuler” ces find dans un with_scope à moins de hacker les libs
self.included(base)
end
end
end
end

Avec les find(:all) de ma_lib prenant bien sûr en compte la
condition [ ‘state = ?’, ‘exported’ ]

J’espère avoir été clair, j’aurais dû apporter plus de précision
sur mon premier post :wink:

Concrètement il n’y a pas d’outil build-in pour faire ca mais tu peux
le faire à la main car il y a tout ce qu’il faut dans rails.

Le plus simple est effectivement de surcharger les methodes en
question, la nature ultra dynamique de ruby fait qu’il n’y a pas de
raison que tu ne puisses pas utiliser ce mécanisme.

Mais si vraiment tu veux éviter tu peux jouer directement avec les
mécanismes de scope de rails.

Il faut savoir que rails stocke le scope dans une variable de class
accessible par la méthode protected scoped_methods. La bonne nouvelle
c’est que Rails se paye le luxe de faire en sorte que ce soit thread
safe.

L’astuce consiste à charger au moment de l’instanciation du
controlleur cette methode scoped_methods avec le scope qui va bien.

Attention cependant car c’est un tableau et pour éviter de rajouter
3000 fois le même scope il faut le netoyer (typiquement au moment du
paramétrage de scope_methods).

Une implémentation possible est de rajouter une methode static à ta
class qui ferait en gros

class Model
class << self
def bind_to_scope
self.unbind
self.scoped_methods << TON_SCOPE
end

def unbind
  self.scoped_methods.clear
end

end
end

et un before filter dans l’application controller qui se contente de
faire un Model.bind_to_scope.

Renaud


#5

Tu peut surcharger le find de ton model et faire en sorte de merger
n’importe quel condition avec quelque chose un peut comme cela

:conditions => [ ‘state = ?’,
‘exported’ ]

J’ai pas ma machine sous la main pour faire un exmeple et tester mais on
devrait pouvoir faire quelque chose comme cela.

Voila HTH.


#6

Super,

Merci à tous les 2 pour m’avoir fait decouvrir le “scope”. Dans mon cas
la
méthode static proposée par Renaud convient parfaitement.
Ceci dit on ne m’enlevera pas de l’idée qu’il serait intéressant de
pouvoir
faire des “vues” (au sens SQL du terme) sur des modeles. Compte tenu du
fait
que la vue SQL n’est pas dans la philosophie Rails pk ne pas pouvoir le
faire sur un modele Rails (sans avoir à charger des methodes protected,
j’entends…).
Pour reprendre mon exemple il serait plus simple et plus clair de coder
dans
le controller :
model :product(:conditions=> [ ‘state = ?’, ‘exported’ ], :include =>
:gamme…)

L’astuce proposée par Renaud va bien dans ce sens mais ce n’est pas le
genre
d’aide que l’on peut trouver dans la doc en ligne ou les bouquins…

Samuel