diff options
Diffstat (limited to 'activerecord/lib/active_record/relation/calculations.rb')
-rw-r--r-- | activerecord/lib/active_record/relation/calculations.rb | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 741f94f777..0b27ea730b 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -1,3 +1,5 @@ +require 'active_support/deprecation' + module ActiveRecord module Calculations # Count the records. @@ -13,16 +15,9 @@ module ActiveRecord # # Person.count(:age, distinct: true) # # => counts the number of different age values - # - # Person.where("age > 26").count { |person| person.gender == 'female' } - # # => queries people where "age > 26" then count the loaded results filtering by gender def count(column_name = nil, options = {}) - if block_given? - self.to_a.count { |item| yield item } - else - column_name, options = nil, column_name if column_name.is_a?(Hash) - calculate(:count, column_name, options) - end + column_name, options = nil, column_name if column_name.is_a?(Hash) + calculate(:count, column_name, options) end # Calculates the average value on a given column. Returns +nil+ if there's @@ -56,13 +51,13 @@ module ActiveRecord # +calculate+ for examples with options. # # Person.sum('age') # => 4562 - # # => returns the total sum of all people's age - # - # Person.where('age > 100').sum { |person| person.age - 100 } - # # queries people where "age > 100" then perform a sum calculation with the block returns def sum(*args) if block_given? - self.to_a.sum(*args) { |item| yield item } + ActiveSupport::Deprecation.warn( + "Calling #sum with a block is deprecated and will be removed in Rails 4.1. " \ + "If you want to perform sum calculation over the array of elements, use `to_a.sum(&block)`." + ) + self.to_a.sum(*args) {|*block_args| yield(*block_args)} else calculate(:sum, *args) end @@ -81,18 +76,17 @@ module ActiveRecord # # values = Person.group('last_name').maximum(:age) # puts values["Drake"] - # => 43 + # # => 43 # # drake = Family.find_by_last_name('Drake') # values = Person.group(:family).maximum(:age) # Person belongs_to :family # puts values[drake] - # => 43 + # # => 43 # # values.each do |family, max_age| # ... # end # - # Examples: # Person.calculate(:count, :all) # The same as Person.count # Person.average(:age) # SELECT AVG(age) FROM people... # @@ -116,8 +110,8 @@ module ActiveRecord 0 end - # Use <tt>pluck</tt> as a shortcut to select a single attribute without - # loading a bunch of records just to grab one attribute you want. + # Use <tt>pluck</tt> as a shortcut to select one or more attributes without + # loading a bunch of records just to grab the attributes you want. # # Person.pluck(:name) # @@ -126,11 +120,9 @@ module ActiveRecord # Person.all.map(&:name) # # Pluck returns an <tt>Array</tt> of attribute values type-casted to match - # the plucked column name, if it can be deduced. Plucking an SQL fragment + # the plucked column names, if they can be deduced. Plucking an SQL fragment # returns String values by default. # - # Examples: - # # Person.pluck(:id) # # SELECT people.id FROM people # # => [1, 2, 3] @@ -187,8 +179,6 @@ module ActiveRecord # Pluck all the ID's for the relation using the table's primary key # - # Examples: - # # Person.ids # SELECT people.id FROM people # Person.joins(:companies).ids # SELECT people.id FROM people INNER JOIN companies ON companies.person_id = people.id def ids @@ -241,6 +231,8 @@ module ActiveRecord # Postgresql doesn't like ORDER BY when there are no GROUP BY relation = reorder(nil) + column_alias = column_name + if operation == "count" && (relation.limit_value || relation.offset_value) # Shortcut when limit is zero. return 0 if relation.limit_value == 0 @@ -251,13 +243,20 @@ module ActiveRecord select_value = operation_over_aggregate_column(column, operation, distinct) + column_alias = select_value.alias relation.select_values = [select_value] query_builder = relation.arel end - result = @klass.connection.select_value(query_builder, nil, relation.bind_values) - type_cast_calculated_value(result, column_for(column_name), operation) + result = @klass.connection.select_all(query_builder, nil, relation.bind_values) + row = result.first + value = row && row.values.first + column = result.column_types.fetch(column_alias) do + column_for(column_name) + end + + type_cast_calculated_value(value, column, operation) end def execute_grouped_calculation(operation, column_name, distinct) #:nodoc: @@ -275,7 +274,7 @@ module ActiveRecord column_alias_for(field) } group_columns = group_aliases.zip(group_fields).map { |aliaz,field| - [aliaz, column_for(field)] + [aliaz, field] } group = group_fields @@ -315,7 +314,10 @@ module ActiveRecord end Hash[calculated_data.map do |row| - key = group_columns.map { |aliaz, column| + key = group_columns.map { |aliaz, col_name| + column = calculated_data.column_types.fetch(aliaz) do + column_for(col_name) + end type_cast_calculated_value(row[aliaz], column) } key = key.first if key.size == 1 |