Sum won't seem to add the fields?!

I have the code which creates the following made up of an array of 3
TreatLists each with a number of Treatlistitems (I’ve broken it up to
make it easier to read).

?> @breakdown
=> [
#<Treatlist:0x23b98ac @items=[
#<Treatlistitem:0x2389ef4 @longname=“Eye Brow Shape”, @spend=17.0,
@prodtreat=“T”, @numsold=2, @unitcost=10.0>]>,

#<Treatlist:0x235df34
@items=[#<Treatlistitem:0x235b16c @longname=“Back Massage”,
@spend=10.0, @prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x23597cc @longname=“Hopi Ear Candles”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x23582dc @longname=“Back Massage (Essential Oils)”,
@spend=10.0, @prodtreat=“T”, @numsold=1, @unitcost=10.0>]>,

#<Treatlist:0x2357a1c @items=[
#<Treatlistitem:0x2351b30 @longname=“Back Massage”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x234f9fc @longname=“Hopi Ear Candles”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x234cf90 @longname=“Eye Brow Shape”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x2349db8 @longname=“Full Leg Wax DSS”, @spend=18.0,
@prodtreat=“T”, @numsold=2, @unitcost=10.0>,
#<Treatlistitem:0x23476bc @longname=“Bridal Make Up”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x2342fcc @longname=“Collin Face Powder”, @spend=10.0,
@prodtreat=“P”, @numsold=1, @unitcost=10.0>]>]

I’m trying to add together the ‘spend’ figures from each but only if
prodtreat = T or P. When I try the following:

@breakdown[1].items.sum{|item| item.spend if item.prodtreat == “T”}
=> 30.0

it works!!!

But when I try it with P …

@breakdown[1].items.sum{|item| item.spend if item.prodtreat == “P”}

I get the following:

NoMethodError: You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.+
from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/
active_support/core_ext/enumerable.rb:63:in sum' from (irb):65:ininject’
from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/
active_support/core_ext/enumerable.rb:63:in each' from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/ active_support/core_ext/enumerable.rb:63:ininject’
from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/
active_support/core_ext/enumerable.rb:63:in sum' from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/ active_support/core_ext/enumerable.rb:61:insum’
from (irb):65

I really have no idea why this is not working or not returning a zero
value?! Any ideas please?

Cheers

Darren

I have also noted that with @breakdown[2] it doesn’t work even though
I know I have a “P” in there!

@breakdown[2]
=> #<Treatlist:0x2357a1c @items=[
#<Treatlistitem:0x2351b30 @longname=“Back Massage”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x234f9fc @longname=“Hopi Ear Candles”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x234cf90 @longname=“Eye Brow Shape”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x2349db8 @longname=“Full Leg Wax DSS”, @spend=18.0,
@prodtreat=“T”, @numsold=2, @unitcost=10.0>,
#<Treatlistitem:0x23476bc @longname=“Bridal Make Up”, @spend=10.0,
@prodtreat=“T”, @numsold=1, @unitcost=10.0>,
#<Treatlistitem:0x2342fcc @longname=“Collin Face Powder”, @spend=10.0,
@prodtreat=“P”, @numsold=1, @unitcost=10.0>]>

@breakdown[2].items.sum{|item| item.spend if item.prodtreat == “P”}

NoMethodError: You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.+
from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/
active_support/core_ext/enumerable.rb:63:in sum' from (irb):68:ininject’
from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/
active_support/core_ext/enumerable.rb:63:in each' from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/ active_support/core_ext/enumerable.rb:63:ininject’
from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/
active_support/core_ext/enumerable.rb:63:in sum' from /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/ active_support/core_ext/enumerable.rb:61:insum’
from (irb):68

This is confusing me mightily!

2009/8/26 Ruby on Rails: Talk [email protected]:

@prodtreat=“T”, @numsold=1, @unitcost=10.0>,

@breakdown[1].items.sum{|item| item.spend if item.prodtreat == “P”}
active_support/core_ext/enumerable.rb:63:in `each’
value?! Any ideas please?
A bit of a guess here but it may be that fact that this will attempt
to include some nil values in the sum as the result of the block will
be nil (I think) for values that do not match. Perhaps this is ok if
the first record is included in the sum but later ones not (so it is
performing value + nil) but fails if the first one is not included in
the sum (so it performs nil + value). Just a guess.

Colin

On Aug 27, 8:03 am, Colin L. [email protected] wrote:

the sum (so it performs nil + value). Just a guess.

That is indeed it - the value of an if statement where the condition
is not met. One way of solving this would be to change the code to

if …
item.spend
else
0
end

Fred

Looks like the following works:

@breakdown[2].items.find_all {|item| item.prodtreat == “T”}.sum{|item|
item.spend}

Really have no idea why? So any help would be enlightening.

Thanks

Darren

PS. Have a feeling that this can be simplified to:

@breakdown[2].items.find_all {|item| item.prodtreat == “T”}.sum
(&:spend)

Hi,

I have pasted a simplified version of the problem you are trying to
understand. You cannot do a ‘sum’ on a collection that has a ‘nil’ as
one of its elements. If ‘nil’ happens to be the first element, you
will get the ‘NoMethodError’ , as the method ‘+’ is called on it (as
shown in the error trace ‘nil.+’) . Also note that the elements of the
collection have to define the method ‘+’ for sum to work.

‘sum’ works by using ‘inject’ which in turn takes the first element
(unless an initial value is provided) and calls + on it using the next
element in collection as the input, then takes the result and repeats
the process for all the rest of the elements

ar = [1,2,3]
=> [1, 2, 3]
ar.sum
=> 6
ar = [nil,2,3]
=> [nil, 2, 3]
ar.sum
NoMethodError: You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.+
from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.3/lib/
active_support/core_ext/enumerable.rb:63:in sum' from (irb):16:in inject’

regards,
mvp

On Aug 26, 10:00 pm, “Ruby on Rails: Talk” [email protected]