This project is archived and is in readonly mode.
Enumerable#sum not called on some association collections
-
Chris Schumann
A failing unit test:
# test/unit/child_test.rb require 'test_helper' class ChildTest < ActiveSupport::TestCase test "should sum ids" do p = Parent.new p.children.build p.save # This one passes assert p.children.find(:all).sum(&:id) > 0 # This one fails assert p.children.sum(&:id) > 0 end end -
Will Bryant
This is the expected current behaviour. Calling some_has_many.sum calls the Calculations module sum, which passes the string argument you give it to the database - so you should use "p.children.sum('id')".
A patch to support loading the target array and delegating the calculation when passing a block instead of a string (which is effectively what you're doing above) to the calculation method (sum etc.) would be welcome.
-
CancelProfileIsBroken
- Tag changed from 2.3.2, enumerable, sum to 2.3.2, bugmash, enumerable, sum
-
Adam Keys
Will, I'm wondering if changing some_has_many.sum to load all records is too sugary. Case in point, I can look at this and think "hey, this is obviously loading a bunch of records into memory":
person.children.all.sum(&:id)
And that this is going to do some aggregate cleverness on the database and avoid huge loads:
Person.all(&:id)
But the changing this to load all the records on the has_many muddies the waters:
person.children.sum(&:id)
Does this do something clever with aggregates or does it load a bunch of objects? Or am I missing something?
-
Dan Pickett
-1 - I disagree that this is a bug -
this is by design to me - the finder should always return an array. conditions should be supplied in the sum call.
-
dira
I agree - this is design, not a bug. -1 for BugMash.
The requested syntactic sugar for has_many has two facets:
- it would cause 'huge loads' from the database if the 'many' are not loaded yet - it would be more efficient if the data is loaded already :)I favor implementation of the suggestion because the some_has_many should support the Enumerable interface.
-
Elad Meidar
-1 here too, seem that it will require too much db attention to avoid huge loads when the association is not memo'd, chaining to #all seem to be the way i would go for.
-
José Valim
-1 For me this is by design too.
I also disagree supporting the Enumerable interface, since they are different things. In Chris case, for example, the proper way to calculate the sum, would be:
@parent.children.sum('id')If we allow people to do this:
@parent.children.sum(&:id)We are giving a shortcut to write non performant code. If you really want to do that, invoking to array looks like the way to go (and it also make obvious what is happening):
@parent.children.to_a.sum(&:id)Could be handy a documentation patch, to explain the differences between AssoicationProxy#sum and Array#sum.
-
Pratik
- State changed from new to invalid
-
José Valim
- Tag changed from 2.3.2, bugmash, enumerable, sum to 2.3.2, enumerable, sum