What's the right way to do counts in Rails?

22,510

Solution 1

I would recommend you to avoid direct access to database in my templates because then you're losing a bit of flexibility when it comes to caching.

Try to prepare all the data you need to render in your action instead and then use meaningful instance variables like @number_of_accounts or @accounts.count.

This will make your views cleaner and easier to debug and also a bit more DRY if you render action in different formats (html, json, etc)

As to how do you get your numbers - it doesn't really matter that much, just move away from find_* methods towards scoping and write readable code

Solution 2

You don't need a name scope to perform a count.

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

But named scopes are an excellent way to make your code more reusable.

Named scopes don't have any noticeable performance impact on your application.

Solution 3

In rails 3 a simple call to count issues a simple count request:

Contact.count

is resolved as:

SELECT COUNT(*) AS count_id FROM "contacts"

a find all by field name will resolve as:

Contact.find_all_by_country("Canada")

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

I would recommend indexing your admin column for faster lookups and this can be translated into a named scope, but that by itself will only predefine the query, not optimize it.

It is important to note that if you issue

Contact.find_all_by_country("Canada").count

count is a method on the array class and doesn't actually issue a count on the database:

Contact.find_all_by_country("Canada").count

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

Solution 4

A named scope shouldn't have an impact on performance

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

Then you can have Account.not_admin.count

Edited per DGM's comment: To check the generated SQL in a console, compare Account.not_admin.to_sql with Account.find_all_by_admin(false).to_sql

Share:
22,510
Gotjosh
Author by

Gotjosh

Updated on July 09, 2022

Comments

  • Gotjosh
    Gotjosh almost 2 years

    I have a rails app with many following pieces of code:

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

    My question is is this the right way to do counts on views? It seems so "dirty" is there a more railish, way to do counts? I'm thinking named scopes perhaps, but I just want to be sure that these type of things won't have a greater impact in performance.

    Thank You,

  • DGM
    DGM over 13 years
    Account.not_admin.count.to_sql is an error, at least in rails 3, since count returns a Fixnum.
  • Jed Schneider
    Jed Schneider over 13 years
    also take a look at this article: railway.at/2010/03/09/named-scopes-are-dead
  • David Sulc
    David Sulc over 13 years
    Oops. Couldn't test here, but you must be correct. However, Account.not_admin.to_sql and Account.find_all_by_admin(false).to_sql should be equivalent.
  • Gotjosh
    Gotjosh over 13 years
    This was the kind of answer i was looking, for I know how to do it, I just wanted to know the BEST way to do it.