Hello,
This may just be my misunderstanding something, but I’m seeing
something strange.
I have a model, Ticket, that in the database table ‘tickets’ has a
field, let’s say ‘seats’.
I can do a Find and retrieve the items:
t = Ticket.find :all
Then do a sum to get the total seats:
s = t.sum(&:seats)
and that returns the correct sum.
Playing in the console, I did:
t.sum(&:seats)
and while returning the correct sum, it also changed the ‘t’ variable
to be just the final item in the array. Is this correct? The sum is
just doing an ‘inject’, which I didn’t think altered the original
array, but maybe I’m wrong?
And here’s a second question, say I want to use the found items, but
restrict the sum to a subset - total all seats that have been sold. I
could do it by doing another find, but can I use .inject with a
condition, so I don’t have to requery the database?
Thanks!
Hmm, not sure on the console based sum findings, I don’t see the same
behavior. On your other question, the sum methods, etc all use
ActiveRecord::Calculations#calculate and it will take a conditions
parameter. See:
http://api.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html#M000969
If your condition is fairly simple and you can just use inject manually:
t = Ticket.find :all
s = t.inject{|sum,n| n.column_you_care_about == ‘some_value’ ? sum +
n.column_to_add : 0}
-Bill
John T. wrote:
t = Ticket.find :all
to be just the final item in the array. Is this correct? The sum is
–
Sincerely,
William P.
On Nov 8, 2007 11:53 AM, William P. [email protected] wrote:
s = t.inject{|sum,n| n.column_you_care_about == ‘some_value’ ? sum +
n.column_to_add : 0}
-Bill
Thanks. I think the weird console behavior may have just been my
stupidity I think I was using the array inside the inject so it was
just assigning to itself. Duh.
I’m trying the simple inject, but for some reason it isn’t totaling
the column. I’m using:
s= t.inject(0) {|total,n| n.picked_up ? (total + n.seats) : 0}
but it’s always coming out 0. (seats is a boolean, and I’m (for now)
using sqlite, so the actual data is ‘t’ or ‘f’ - but looking at one
record displays correctly - t[2].picked_up is true) I tried using
n.picked_up? and n.picked_up == true
Doing: t[2].picked_up ? “Y” : “N” correctly returns “Y”
Thanks,
jt
On Nov 8, 2007 11:29 AM, John T. [email protected] wrote:
t = Ticket.find :all
Then do a sum to get the total seats:
s = t.sum(&:seats)
It is much more efficient to use the AR calculation methods:
s = Ticket.sum(:seats)
The first one retrieves all of the rows and instantiates an AR
object for each. The second issues a single query that returns one
number.
and that returns the correct sum.
Playing in the console, I did:
t.sum(&:seats)
and while returning the correct sum, it also changed the ‘t’ variable
to be just the final item in the array. Is this correct? The sum is
just doing an ‘inject’, which I didn’t think altered the original
array, but maybe I’m wrong?
Dunno. I don’t see that behavior. The sum() method you’re using there
is not the ActiveRecord::Base.sum method, but the Enumerable#sum
method added by active support.
On 8 Nov 2007, at 17:10, John T. wrote:
s= t.inject(0) {|total,n| n.picked_up ? (total + n.seats) : 0}
but it’s always coming out 0. (seats is a boolean, and I’m (for now)
using sqlite, so the actual data is ‘t’ or ‘f’ - but looking at one
record displays correctly - t[2].picked_up is true) I tried using
n.picked_up? and n.picked_up == true
the result of your block needs to be the running total - not the value
of the individual term, ie
n.picked_up ? (total + n.seats) : total
Fred
On Nov 8, 2007 12:21 PM, Frederick C. [email protected]
wrote:
the result of your block needs to be the running total - not the value
of the individual term, ie
n.picked_up ? (total + n.seats) : total
Fred
Ahhh… thanks for the clarification… I had a feeling I was missing
something simple
On Nov 8, 2007 12:16 PM, Bob S. [email protected] wrote:
The first one retrieves all of the rows and instantiates an AR
object for each. The second issues a single query that returns one
number.
True, but I had already performed the Find that would then be passed
along to my view, so I figured one less trip to the database - and if
I also want a sum of seats not picked up, I’d then make yet another
trip to the DB.
Dunno. I don’t see that behavior. The sum() method you’re using there
is not the ActiveRecord::Base.sum method, but the Enumerable#sum
method added by active support.
Yeah, I think that was just my dumb error.
I also got the .inject method to work by doing instead:
s= t.inject(0) {|total,n| total + (n.picked_up ? n.seats : 0)}
Sorry Tom, this was my fault. There way a typo in my original post. Glad
you got it working.
-Bill
John T. wrote:
Ahhh… thanks for the clarification… I had a feeling I was missing
something simple
–
Sincerely,
William P.