2009-01-04 8 views
12

Rails gourous: Je viens de découvrir named_scope grâce à un autre utilisateur SO. :)Utilisation de named_scope pour obtenir le nombre de lignes

J'aimerais obtenir le nombre d'un ensemble de lignes, c'est-à-dire un SELECT COUNT(*). De plus, je veux toujours pouvoir chaîner des étendues nommées dans l'appel.

Est-ce un usage légitime (quoique bizarre) de portée nommée?

named_scope :count, :select => "COUNT(*) as count_all" 

Alors je peux le faire (par exemple):

@foobar = Foobar.count.scope.scope.scope 

Le compte est accessible via @foobar.first.count_all.

(modifié pour répondre aux commentaires de Allan)

Vous pouvez faire:

@foobar = Foobar.scope.scope.scope.size 

Mais cela causerait une requête de résultat et non la plus rapide requête SELECT COUNT(*). J'ai une grande quantité de lignes dans la base de données que j'interroge.

Y a-t-il une meilleure façon de procéder?

Répondre

20

La fonctionnalité que vous cherchez est construit dans

Foobar.count # SELECT count(*) AS count_all FROM "foobars" 
Foobar.named_scope.count # SELECT count(*) AS count_all FROM "foobars" WHERE .... 

Si vous exécutez script/server en mode de développement, vous verrez les requêtes lors de leur exécution.

+3

Duh. Parfois, les choses sont si faciles dans les rails que l'évidence me manque. Merci! – unknownuser

+0

S'il vous plaît corrigez-moi si je suis usé mais cela ne semble pas fonctionner si votre portée nommée ressemble à ceci: def self.with_full_name select ("users. *, CONCAT (prénom, nom de famille) AS full_name") fin –

2

Je ne pense pas que ce soit correct du tout. Les étendues sont utilisées pour affiner les instructions find et la requête de comptage ne fonctionnera pas bien avec celles-ci.

2

Il y a une meilleure façon de faire cela, les rails vous donnent déjà les moyens.

En utilisant votre exemple, vous pouvez simplement faire ceci:

@foobar_size = Foobar.all.size #returns integer equal to total rows of Foobar 

et même portée comme ceci:.

@banned_foobars = Foobar.scope_to_find_banned.size #returns integer equal to total rows for "scope_to_find_banned" 
+0

C'est ce que j'avais d'abord essayé. Le problème avec ceci est qu'il ne profite pas du fait que SELECT COUNT (*) est une requête relativement rapide. Il ferait une requête de ligne, et est beaucoup plus lent. – unknownuser

+0

Ah! Je vois ce que tu veux dire. S'il vous plaît pardonnez mon malentendu. –

Questions connexes