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:in `inject'   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:in `inject'   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:in `sum'   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:in `inject'   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:in `inject'   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:in `sum'   from (irb):68

This is confusing me mightily!

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)

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

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

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" <dazzaroo...@gmail.com> wrote: