Andrew_Vit
(Andrew Vit)
October 18, 2013, 12:55am
1
I’d like to try and revive discussion around these issues:
opened 09:39AM - 21 Jul 12 UTC
closed 10:24AM - 05 Nov 12 UTC
activerecord
See [runnable code example](https://gist.github.com/3155195) in gist.
**Goal:**… get a count of rows from a query that includes pseudo columns and grouping.
When counting with grouping in the relation, ActiveRecord tries to return group counts instead of a total count and drops the SELECT on the floor. If there are pseudo-columns in the SELECT for grouping, this breaks the whole query.
Also, if it even worked, this would return a hash instead of a Fixnum. There doesn't
seem to be a way to get the total of returned rows, ignoring the grouping.
- `count` should be usable to return a numeric count even when grouping is needed for the query.
- `relation.count` and `relation.all.count` should have the same semantics.
- `count` should work directly on any relation, so the relation can still be used as a chainable scope.
Suggestion for Rails 4: The Calculations#count method is too ambiguous and assumes too much. Change Calculations#count method to only return groups if a :group option is passed directly to the count method, i.e. do not trigger grouped counts based on other `group_values` in the relation. That, or split #count and #count_grouped into separate methods. This might make it easier to do the right thing with the query builder.
A simple first step might be to flag the relation so that it conditionally delegates `.count` to `.all.count` when the above situation occurs. Thoughts?
opened 02:19AM - 23 Sep 11 UTC
closed 01:41PM - 26 Jul 14 UTC
Pretend I have a OutlandishClaim model, and each claim can have many sources.
`… ``
class OutlandishClaim < ActiveRecord::Base
has_many :sources, :as => :sourceable
scope: sourced, joins(:sources).group("sourceable_id")
end
```
I'd like to get a list of all the OutlandishClaims that have been sourced. BUT, I can't do the following
```
OutlandishClaim.sourced.count
```
because it returns an ordered hash. It seems the _count_ method is reading the _group_ on the scope and thinking that I'd actually called
```
OutlandishClaim.sourced.count(:group => "sourceable_id")
```
This behaviour requires anyone using this scope to know to call _count_ again on the hash to get the actual count. A la
```
OutlandishClaim.sourced.count.count
```
Unfortunately this is lame and also instantiates each record and then counts them. How it _should_ work is that count ignores any chained _group_ on the scope and only groups if you explicitly pass the option to _count_. This would allow for consistent counting behaviour, and in cases where I wanted it grouped, I could simply do as the Rails documentation states and pass the option to the _count_ method.
Originally, my thought for an easy solution was to hide the presence of group_values inside a subquery using from(relation.group(x)).count
as I suggested here:
https://groups.google.com/forum/#!topic/rubyonrails-core/mwBehQcEduU
SELECT COUNT(*) FROM (SELECT * FROM … GROUP BY …)
Unfortunately some databases (MySQL) are really inefficient at dealing with functions on subqueries like this. And ultimately, relying on subqueries to fix it for us is a hack just to get around the problem with blindly calling count
and expecting an integer. I keep running into this problem regularly enough that I really want to work something out for separate and predictable “row count” and “grouped count” methods. Maybe something like one of these ideas I sketched out:
calculations_a.rb
# Goal: split responsibilities of count and grouped_count so they are responsible for returning
# count => Fixnum and grouped_count => Hash in all cases
#
# This option removes original calculation options for count(:group => x)
# in favour of grouped_count(:group => x)
#
# (I'm showing count and average as examples of optional & required column_name params,
# but this would apply to all calculation methods.)
relation = Post.group("author_id").order("created_at")
This file has been truncated. show original
calculations_b.rb
# Goal: keep existing methods for compatibility & familiarity, requiring
# explicit {:group => x} option for a Hash, else return a numeric value.
#
# This option keeps the original calculation methods and just adds grouped_count
# as a shortcut wrapper for using existing group_values from the relation, instead of
# requiring it be specified.
#
# (I'm showing count and average as examples of optional & required column_name params,
# but this would apply to all calculation methods.)
This file has been truncated. show original
Is there a way forward?
Andrew Vit