Enumeration sum

Any idees why I can do this: @sum = @selected.inject(0) { |sum, player| sum + player.value }

but not this: @sum = @selected.sum { |player| player.value } @sum = @selected.sum(&:value)

The last two give me following error:

wrong number of arguments (1 for 2)

/Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_collection.rb:164:in `calculate' /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_collection.rb:164:in `send' /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_collection.rb:164:in `method_missing' /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1693:in `with_scope' /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_collection.rb:164:in `send' /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_collection.rb:164:in `method_missing' /Library/Ruby/Gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_collection.rb:47:in `sum' app/controllers/player_controller.rb:31:in `select'

Any idees why I can do this: @sum = @selected.inject(0) { |sum, player| sum + player.value }

but not this: @sum = @selected.sum { |player| player.value } @sum = @selected.sum(&:value)

The last two give me following error:

Because rails redefines sum so that you can do
some_association.sum :some_column_name

Fred

Frederick Cheung wrote:

Because rails redefines sum so that you can do some_association.sum :some_column_name

More specifically, the #sum method on an ActiveRecord collection proxy queries the database with the argument provided.

If you want to use more complex summations you can using what you're used to with inject by saying:

@sum = @selected.to_a.sum { |player| player.value }

Or a more complex summation:

@sum = @selected.to_a.sum { |player| player.value + player.handicap }

Cheers,   Daniel

Say you have a players table with a score field in it and you want to find the combined score of all players.

Player.find(:all, :select => “score”).map(&:score).sum