Skip to content

Commit 9cc2bf6

Browse files
chrisfinnecarlosantoniodasilva
authored andcommitted
Allow blocks for count with ActiveRecord::Relation. Document and test that sum allows blocks
1 parent 6f1d9d0 commit 9cc2bf6

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

activerecord/lib/active_record/relation/calculations.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,16 @@ module Calculations
1616
#
1717
# Person.count(:age, distinct: true)
1818
# # => counts the number of different age values
19+
#
20+
# Person.where("age > 26").count { |person| gender == 'female' }
21+
# # => queries people where "age > 26" then count the loaded results filtering by gender
1922
def count(column_name = nil, options = {})
20-
column_name, options = nil, column_name if column_name.is_a?(Hash)
21-
calculate(:count, column_name, options)
23+
if block_given?
24+
self.to_a.count { |*block_args| yield(*block_args) }
25+
else
26+
column_name, options = nil, column_name if column_name.is_a?(Hash)
27+
calculate(:count, column_name, options)
28+
end
2229
end
2330

2431
# Calculates the average value on a given column. Returns +nil+ if there's
@@ -52,9 +59,13 @@ def maximum(column_name, options = {})
5259
# +calculate+ for examples with options.
5360
#
5461
# Person.sum('age') # => 4562
62+
# # => returns the total sum of all people's age
63+
#
64+
# Person.where('age > 100').sum { |person| person.age - 100 }
65+
# # queries people where "age > 100" then perform a sum calculation with the block returns
5566
def sum(*args)
5667
if block_given?
57-
self.to_a.sum(*args) {|*block_args| yield(*block_args)}
68+
self.to_a.sum(*args) { |*block_args| yield(*block_args) }
5869
else
5970
calculate(:sum, *args)
6071
end

activerecord/test/cases/calculations_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,22 @@ def test_count_with_from_option
376376
Company.where(:type => "Firm").from('companies').count(:type)
377377
end
378378

379+
def test_count_with_block_acts_as_array
380+
accounts = Account.where('id > 0')
381+
assert_equal Account.count, accounts.count { true }
382+
assert_equal 0, accounts.count { false }
383+
assert_equal Account.where('credit_limit > 50').size, accounts.count { |account| account.credit_limit > 50 }
384+
assert_equal Account.count, Account.count { true }
385+
assert_equal 0, Account.count { false }
386+
end
387+
388+
def test_sum_with_block_acts_as_array
389+
accounts = Account.where('id > 0')
390+
assert_equal Account.sum(:credit_limit), accounts.sum { |account| account.credit_limit }
391+
assert_equal Account.sum(:credit_limit) + Account.count, accounts.sum{ |account| account.credit_limit + 1 }
392+
assert_equal 0, accounts.sum { |account| 0 }
393+
end
394+
379395
def test_sum_with_from_option
380396
assert_equal Account.sum(:credit_limit), Account.from('accounts').sum(:credit_limit)
381397
assert_equal Account.where("credit_limit > 50").sum(:credit_limit),

0 commit comments

Comments
 (0)