Skip to content
This repository
Browse code

Allow blocks for count with ActiveRecord::Relation. Document and test…

… that sum allows blocks
  • Loading branch information...
commit 9cc2bf69ce296b7351dc612a8366193390a305f3 1 parent 6f1d9d0
chrisfinne authored carlosantoniodasilva committed
17  activerecord/lib/active_record/relation/calculations.rb
@@ -16,9 +16,16 @@ module Calculations
16 16
     #
17 17
     #   Person.count(:age, distinct: true)
18 18
     #   # => 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
19 22
     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
22 29
     end
23 30
 
24 31
     # Calculates the average value on a given column. Returns +nil+ if there's
@@ -52,9 +59,13 @@ def maximum(column_name, options = {})
52 59
     # +calculate+ for examples with options.
53 60
     #
54 61
     #   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
55 66
     def sum(*args)
56 67
       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) }
58 69
       else
59 70
         calculate(:sum, *args)
60 71
       end
16  activerecord/test/cases/calculations_test.rb
@@ -376,6 +376,22 @@ def test_count_with_from_option
376 376
         Company.where(:type => "Firm").from('companies').count(:type)
377 377
   end
378 378
 
  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
+
379 395
   def test_sum_with_from_option
380 396
     assert_equal Account.sum(:credit_limit), Account.from('accounts').sum(:credit_limit)
381 397
     assert_equal Account.where("credit_limit > 50").sum(:credit_limit),

0 notes on commit 9cc2bf6

Peter Suschlik

This should read Person.where("age > 26").count { |person| person.gender == 'female' }

Please sign in to comment.
Something went wrong with that request. Please try again.