mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #24203 from sferik/count_with_block
Forward ActiveRecord::Relation#count to Enumerable#count if block given
This commit is contained in:
commit
8fffee4b1c
5 changed files with 28 additions and 6 deletions
|
@ -246,9 +246,12 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
# Count all records using SQL. Construct options and pass them with
|
||||
# scope to the target class's +count+.
|
||||
# Returns the number of records. If no arguments are given, it counts all
|
||||
# columns using SQL. If one argument is given, it counts only the passed
|
||||
# column using SQL. If a block is given, it counts the number of records
|
||||
# yielding a true value.
|
||||
def count(column_name = nil)
|
||||
return super if block_given?
|
||||
relation = scope
|
||||
if association_scope.distinct_value
|
||||
# This is needed because 'SELECT count(DISTINCT *)..' is not valid SQL.
|
||||
|
|
|
@ -715,12 +715,13 @@ module ActiveRecord
|
|||
end
|
||||
alias uniq distinct
|
||||
|
||||
# Count all records using SQL.
|
||||
# Count all records.
|
||||
#
|
||||
# class Person < ActiveRecord::Base
|
||||
# has_many :pets
|
||||
# end
|
||||
#
|
||||
# # This will perform the count using SQL.
|
||||
# person.pets.count # => 3
|
||||
# person.pets
|
||||
# # => [
|
||||
|
@ -728,8 +729,13 @@ module ActiveRecord
|
|||
# # #<Pet id: 2, name: "Spook", person_id: 1>,
|
||||
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
|
||||
# # ]
|
||||
def count(column_name = nil)
|
||||
@association.count(column_name)
|
||||
#
|
||||
# Passing a block will select all of a person's pets in SQL and then
|
||||
# perform the count using Ruby.
|
||||
#
|
||||
# person.pets.count { |pet| pet.name.include?('-') } # => 2
|
||||
def count(column_name = nil, &block)
|
||||
@association.count(column_name, &block)
|
||||
end
|
||||
|
||||
# Returns the size of the collection. If the collection hasn't been loaded,
|
||||
|
|
|
@ -37,8 +37,12 @@ module ActiveRecord
|
|||
# Note: not all valid {Relation#select}[rdoc-ref:QueryMethods#select] expressions are valid #count expressions. The specifics differ
|
||||
# between databases. In invalid cases, an error from the database is thrown.
|
||||
def count(column_name = nil)
|
||||
if block_given?
|
||||
to_a.count { |*block_args| yield(*block_args) }
|
||||
else
|
||||
calculate(:count, column_name)
|
||||
end
|
||||
end
|
||||
|
||||
# Calculates the average value on a given column. Returns +nil+ if there's
|
||||
# no row. See #calculate for examples with options.
|
||||
|
|
|
@ -482,6 +482,10 @@ class CalculationsTest < ActiveRecord::TestCase
|
|||
assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).reverse_order.count
|
||||
end
|
||||
|
||||
def test_count_with_block
|
||||
assert_equal 4, Account.count { |account| account.credit_limit.modulo(10).zero? }
|
||||
end
|
||||
|
||||
def test_should_sum_expression
|
||||
# Oracle adapter returns floating point value 636.0 after SUM
|
||||
if current_adapter?(:OracleAdapter)
|
||||
|
|
|
@ -1086,6 +1086,11 @@ class RelationTest < ActiveRecord::TestCase
|
|||
assert_equal 9, posts.where(:comments_count => 0).count
|
||||
end
|
||||
|
||||
def test_count_with_block
|
||||
posts = Post.all
|
||||
assert_equal 10, posts.count { |p| p.comments_count.even? }
|
||||
end
|
||||
|
||||
def test_count_on_association_relation
|
||||
author = Author.last
|
||||
another_author = Author.first
|
||||
|
|
Loading…
Reference in a new issue