Skip to content


Subversion checkout URL

You can clone with
Download ZIP


ActiveRecord: sum expression returns string '0' for no records, fixed #7439

merged 1 commit into from

6 participants


The bug:

Account.where('1 = 2').sum("2 * credit_limit") => '0'

That is, sum with an expression (not a column name) on a condition or collection that returns no records returns the string "0", whereas it should return an integer, 0.


There was a reason it returned a string - calling to_d on a Fixnum in Ruby 1.8 would give a NoMethodError. This is no longer the case in Ruby 1.9 so it's probably okay to change.

The relevant Lighthouse tickets are 1066 and 4633 - to quote myself from 1066:

The problem with type casting to float for decimal columns and then back to decimal is that you may introduce floating point precision errors. My view would be that if we are doing a straightforward sum on a column then typecast to that column's type otherwise return a string and leave it to the developer to cast to whatever they want. This would also apply to average as well.


I ran the tests, everything passes, and the code looks legit.

The test matches the bug and matches the style of the tests around it.


I haven't had a chance to test this under 1.8.7 yet, but having read through the code it appears as though it handles a missing to_d by casting to string first, see here in connection_adapters/column.rb:

def value_to_decimal(value)
  # Using .class is faster than .is_a? and
  # subclasses of BigDecimal will be handled
  # in the else clause
  if value.class == BigDecimal
  elsif value.respond_to?(:to_d)

BTW: is there an easy way to run the tests under 1.8.7? I had trouble running bundler (due to use of new hash syntax in rails/Gemfile)...


I haven't had a chance to test this under 1.8.7 yet,

You don't need to. We don't support 1.8.7 on master.


@refractalize the change looks fine, but it needs a changelog entry, can you please add that and squash everything into one commit if necessary? Thanks.


@carlosantoniodasilva - took a while to get around to the changelog entry, all done now.

@tenderlove tenderlove merged commit 0a78417 into rails:master

@refractalize awesome, thanks, and sorry for the delay :)


Nice one, thanks all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
5 activerecord/
@@ -906,3 +906,8 @@
*Aaron Patterson*
Please check [3-2-stable]( for previous changes.
+* Fix bug where sum(expression) returns string '0' for no matching records
+ Fixes #7439
+ *Tim Macfarlane*
2  activerecord/lib/active_record/relation/calculations.rb
@@ -349,7 +349,7 @@ def column_for(field)
def type_cast_calculated_value(value, column, operation = nil)
case operation
when 'count' then value.to_i
- when 'sum' then type_cast_using_column(value || '0', column)
+ when 'sum' then type_cast_using_column(value || 0, column)
when 'average' then value.respond_to?(:to_d) ? value.to_d : value
else type_cast_using_column(value, column)
4 activerecord/test/cases/calculations_test.rb
@@ -378,6 +378,10 @@ def test_should_sum_expression
+ def test_sum_expression_returns_zero_when_no_records_to_sum
+ assert_equal 0, Account.where('1 = 2').sum("2 * credit_limit")
+ end
def test_count_with_from_option
assert_equal Company.count(:all), Company.from('companies').count(:all)
assert_equal Account.where("credit_limit = 50").count(:all),
Something went wrong with that request. Please try again.