EastsideDev
EastsideDev

Reputation: 6659

Calculating the sum of values of a given column

rails 3.2

Invoice.sum(:amount)

Accurately returns the sum of all values in the amount column.

If I do the following:

invoices = Invoice.all

And then:

invoices.sum(:amount)

I get the following error:

NoMethodError: undefined method `+'

Is there a way to do this?

Upvotes: 2

Views: 2532

Answers (3)

sammms
sammms

Reputation: 677

This is because #sum is an ActiveRecord method. What it is essentially doing is building the aggregation into your database query like so (in SQL):

SELECT SUM(name_of_column_to_sum) FROM table_name;

If you want to return the values and store them in a variable (#all),

SELECT * FROM table_name;

and THEN sum them, you are no longer working with an ActiveRecord query, but rather an ActiveRecord relation (an array-like object that is returned from the ActiveRecord query). So, at that point you would need to use vanilla Ruby to sum up. You could use #map and then #sum, but it would be faster and cleaner to just use #inject, like so:

invoices.inject(0){ |sum, invoice| sum + invoice.amount }

Upvotes: 3

Kkulikovskis
Kkulikovskis

Reputation: 2088

If you are certain that there is not a single amount == nil then what you tried, should work. If you have a single nil column this would result in NoMethodError: undefined method '+' for nil. In this case you can either do invoices.map(&:amount).compact.sum or invoices.sum { |i| i.amount || 0 }

Upvotes: 3

Gustavo Fe
Gustavo Fe

Reputation: 64

You have to use map function, like this:

invoices.map(&:amount).sum

Upvotes: 1

Related Questions