As you can see, Thing.distinct.size is mis-reporting the size of the
result. I can't figure out what's causing this, or why adding .all
fixes it. Running the query straight into the database predictably
returns just one record:
SELECT * FROM "things" GROUP BY name;
id = 2
name = a
created_at = 2009-10-16 02:34:28
updated_at = 2009-10-16 02:34:28
I just stumbled upon the same problem... From what I can tell,
ActiveRecord doesn't add the GROUP BY clause when it's doing a COUNT.
Take a look in your log. You should see two nearly identical queries,
but one will be a SELECT with the GROUP BY and one will be a COUNT
without the GROUP BY.
Something like this:
SELECT things.* FROM things GROUP BY name
and then
SELECT COUNT(*) AS count_all FROM things; # NO GROUP BY!
The thing is, GROUP BY with an aggregate function will return the
number of items in each group. So if you have 3 Things, "a", "a", and
"b", adding a GROUP BY at the end of the COUNT query will give you
something like this:
That makes sense - I was thinking of what named_scope returns as an
Array, when really it's ActiveRecord::NamedScope::Scope. I see now in
the source that it just delegates Array methods to find(:all), which
is why you can do things like Thing.distinct.each and why
Thing.distinct.to_s returns an Array's string notation. I'm not sure
why it has to define a size method, that seems like something it could
just hand off to find(:all) too.