2010-12-14 59 views
5

J'ai une application rails avec de nombreux morceaux de code suivants:Quelle est la bonne façon de faire des comptes dans Rails?

Our active community of <%= Account.find_all_by_admin(false).count %> 

Ma question est est-ce la bonne façon de faire compte sur des vues? Il semble si "sale" y a-t-il un plus railish, moyen de faire des comptes? Je pense peut-être à des portées nommées, mais je veux juste être sûr que ce genre de choses n'aura pas plus d'impact sur les performances.

Merci,

Répondre

6

Je vous recommande d'éviter l'accès direct à la base de données dans mes modèles, car vous perdez un peu de flexibilité en matière de mise en cache.

Essayez de préparer à la place toutes les données dont vous avez besoin, puis utilisez des variables d'instance significatives telles que @number_of_accounts ou @accounts.count.

Cela rendra votre point de vue plus propre et plus facile à déboguer et aussi un peu plus sec si vous rendre l'action dans différents formats (html, JSON, etc)

Quant à comment obtenez-vous vos chiffres - il n » t vraiment d'importance tant que ça, il suffit de déplacer loin des méthodes find_ * vers la portée et écrire un code lisible

+0

Ce fut le genre de réponse Je regardais, car je sais comment le faire, je voulais juste savoir la meilleure façon de le faire. – Gotjosh

2

Un champ nommé ne devrait pas avoir un impact sur les performances

scope :not_admin, where(:admin => false) 

Ensuite, vous pouvez avoir Account.not_admin.count

Edité par le commentaire de DGM: Pour vérifier le SQL généré dans un console, comparer Account.not_admin.to_sql avec Account.find_all_by_admin(false).to_sql

+0

'Account.not_admin.count.to_sql' est une erreur, au moins dans des rails 3, étant donné que le nombre renvoie un Fixnum. – DGM

+0

Oups. Impossible de tester ici, mais vous devez être correct. Toutefois, Account.not_admin.to_sql et Account.find_all_by_admin (false) .to_sql doivent être équivalents. –

1

Dans les rails 3 un simple appel à compter émet un simple demande unt:

Contact.count 

est résolu que:

SELECT COUNT(*) AS count_id FROM "contacts" 

a trouver tous par leur nom de domaine résoudra comme:

Contact.find_all_by_country("Canada") 

SELECT "contacts".* FROM "contacts" WHERE ("contacts"."country" = 'Canada') 

je recommande l'indexation de votre colonne d'administration pour accélérer les recherches et ce peut être traduit dans une portée nommée, mais cela en soi ne fera que prédéfinir la requête, et non l'optimiser.

Il est important de noter que si vous émettez

Contact.find_all_by_country("Canada").count 

count est une méthode sur la classe de tableau et ne délivre pas vraiment un compte sur la base de données:

Contact.find_all_by_country("Canada").count 

SELECT "contacts".* FROM "contacts" WHERE ("contacts"."country" = 'Canada') 
+0

jeter un oeil à cet article: http://www.railway.at/2010/03/09/named-scopes-are-dead/ –

+0

+1 pour le Canada, eh ;-) – Ted

7

Vous n » t besoin d'une portée de nom pour effectuer un comptage. Mais les portées nommées sont un excellent moyen de rendre votre code plus réutilisable.

Les étendues nommées n'ont aucun impact notable sur les performances de votre application.

0

Vous pouvez utiliser la requête suivante au lieu de Account.where(:admin => false).count

Account.select(:id).where(:admin => false).count 

Il suffit de sélectionner une colonne, au lieu de sélectionner tous. Il génère la requête suivante, et il est plus rapide que la précédente:

SELECT COUNT("accounts"."id") FROM "accounts" where admin = false