count v.s. lenght v.s. size
there are couple difference between count and length, generally speaking, count does’t load the array so it is faster. However, there are situation count won’t give you an accurate number
here is an example
suppose you have three tables ‘users’, ‘roles’, and the join table ‘roles_users’, and you want to all active users that has role of ‘user’ or ‘admin’
Here is how to get it in rails:
named_scope :active, :joins=> :roles, :conditions=>['state=? and roles.name in (?) ', 'active', ['user', 'admin'] ], :group=>'id'
here group is necessary otherwise you will get duplicate users records if users has more than one role.
Here is where length different than count:
say joe is the only user and he has both user and admin roles
User.active.count # returns 2 User.active.length # returns 1
It is easy to figure out why through SQL:
the named_scope translate to
select u.id, u.first_name, u.email from users u inner join roles_users ru on ru.user_id = u.id inner join roles r on r.id = ru.role_id where u.state = 'active' and r.name in ('user', 'admin') group by u.id;
the count translates to
select count(*), u.id, u.first_name, u.email from users u inner join roles_users ru on ru.user_id = u.id inner join roles r on r.id = ru.role_id where u.id = 2 and r.name in ('user', 'admin') group by u.id;
without group by +----+------------+--------------------+ | id | first_name | email | +----+------------+--------------------+ | 1 | Joe | joe@example.com | | 1 | Joe | joe@example.com | +----+------------+--------------------+ 5 rows in set (0.00 sec) with group by +----+------------+--------------------+ | id | first_name | email | +----+------------+--------------------+ | 1 | Joe | joe@example.com | +----+------------+--------------------+ 1 row in set (0.00 sec) using count and here is why it returns 2 +----------+----+------------+--------------------+ | count(*) | id | first_name | email | +----------+----+------------+--------------------+ | 2 | 1 | Joe | joe@example.com | +----------+----+------------+--------------------+ 1 row in set (0.00 sec)
the bottom line: don’t use count when using :group
p.s. for more difference between length, size and count, read this blog post: http://rhnh.net/2007/09/26/counting-activerecord-associations-count-size-or-length