Je viens de découvrir un truc génial (encore un):
Ceux qui ont fait des appli qui accèdent à la base de donnée auront surement déjà au besoin d'ajouter des méthodes du genre Adresse.findByCodePostal(codepostal).
Evidement à chaque fois on a jamais celle qui nous faut... avec hibernate le code est relativement simple à écrire. Mais avec Rails c'est encore plus simple! Il n'y a pas besoin de l'écrire!
Imaginons que j'ai une table items avec comme colonne "title", "quantity", "price"...
J'écris directement (dans mon test unitaire par exemple):
En fait les find_by_xxx() sont créées à la volée! C'est génial! Il suffit que mon champs existe en base et la méthode correspondante existe toute seule!
Ceux qui ont fait des appli qui accèdent à la base de donnée auront surement déjà au besoin d'ajouter des méthodes du genre Adresse.findByCodePostal(codepostal).
Evidement à chaque fois on a jamais celle qui nous faut... avec hibernate le code est relativement simple à écrire. Mais avec Rails c'est encore plus simple! Il n'y a pas besoin de l'écrire!
Imaginons que j'ai une table items avec comme colonne "title", "quantity", "price"...
J'écris directement (dans mon test unitaire par exemple):
Item.find_by_title('test title') Item.find_by_quantity(8) Item.find_by_price(123.45)
En fait les find_by_xxx() sont créées à la volée! C'est génial! Il suffit que mon champs existe en base et la méthode correspondante existe toute seule!
2 commentaires:
Perso, ActiveRecord et le MDA de rails sont les arguments de choc qui m'ont fait lorgner du côté de ce framework ^^
Rails utilise en effet le 'method_missing' de ActiveRecord:Base : si la méthode n'existe pas, on fait tout de même un match d'expression régulière sur
find_by_*(_and_*)
et find_all_by_* (qui doit être deprecated).
Si ça match, on extrait les "argument" de l'expression : si le(s) * sont des champs, on construit la requête.
C'est magique.
Néanmoins, l'utilisation de method_missing montre la limite de ce genre de bidouille, ma fois agréable.
Coté perfs, faut faire un benchmark.
Il est possible de surcharger ActiveRecord:Base avec :
def find_by(match, *conditions)
..
end
et
def find_all_by(match, *conditions)
..
end
qui prennent la premiere chaine comme match, et les suivantes comme conditions.
Par exemple :
@me = Person.find_by name_and_age_and_city 'john' 24 'Paris'
Ne reste plus qu'à traiter le match comme method_missing le fait déjà. Au moins, on passe plus par gestion des exceptions, mais bien par un controle en amont.
--
Un article à ce sujet :
http://blog.hasmanythrough.com/2006/8/13/how-dynamic-finders-work
Le code source : http://dev.rubyonrails.org/browser/trunk/activerecord/lib/active_record/base.rb
Enregistrer un commentaire