0
+ module Calculations
#:nodoc:0
CALCULATIONS_OPTIONS = [:conditions, :joins, :order, :select, :group, :having, :distinct]
0
def self.included(base)
0
base.extend(ClassMethods)
0
@@ -143,83 +143,83 @@ module ActiveRecord
0
- def construct_calculation_sql(aggregate, aggregate_alias, options)
0
- sql = ["SELECT #{aggregate} AS #{aggregate_alias}"]
0
- sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group]
0
- sql << " FROM #{table_name} "
0
- add_joins!(sql, options, scope)
0
- add_conditions!(sql, options[:conditions], scope)
0
- sql << " GROUP BY #{options[:group_field]}" if options[:group]
0
- sql << " HAVING #{options[:having]}" if options[:group] && options[:having]
0
- sql << " ORDER BY #{options[:order]}" if options[:order]
0
- def execute_simple_calculation(operation, column_name, column, aggregate, aggregate_alias, options)
0
- value = connection.select_value(construct_calculation_sql(aggregate, aggregate_alias, options))
0
- type_cast_calculated_value(value, column, operation)
0
+ def construct_calculation_sql(aggregate, aggregate_alias, options) #:nodoc:
0
+ sql = ["SELECT #{aggregate} AS #{aggregate_alias}"]
0
+ sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group]
0
+ sql << " FROM #{table_name} "
0
+ add_joins!(sql, options, scope)
0
+ add_conditions!(sql, options[:conditions], scope)
0
+ sql << " GROUP BY #{options[:group_field]}" if options[:group]
0
+ sql << " HAVING #{options[:having]}" if options[:group] && options[:having]
0
+ sql << " ORDER BY #{options[:order]}" if options[:order]
0
- def execute_grouped_calculation(operation, column_name, column, aggregate, aggregate_alias, options)
0
- group_attr = options[:group].to_s
0
- association = reflect_on_association(group_attr.to_sym)
0
- associated = association && association.macro == :belongs_to # only count belongs_to associations
0
- group_field = (associated ? "#{options[:group]}_id" : options[:group]).to_s
0
- group_alias = column_alias_for(group_field)
0
- group_column = column_for group_field
0
- sql = construct_calculation_sql(aggregate, aggregate_alias, options.merge(:group_field => group_field, :group_alias => group_alias))
0
- calculated_data = connection.select_all(sql)
0
- key_ids = calculated_data.collect { |row| row[group_alias] }
0
- key_records = association.klass.base_class.find(key_ids)
0
- key_records = key_records.inject({}) { |hsh, r| hsh.merge(r.id => r) }
0
+ def execute_simple_calculation(operation, column_name, column, aggregate, aggregate_alias, options) #:nodoc:
0
+ value = connection.select_value(construct_calculation_sql(aggregate, aggregate_alias, options))
0
+ type_cast_calculated_value(value, column, operation)
0
- calculated_data.inject(OrderedHash.new) do |all, row|
0
- key = associated ? key_records[row[group_alias].to_i] : type_cast_calculated_value(row[group_alias], group_column)
0
- value = row[aggregate_alias]
0
- all << [key, type_cast_calculated_value(value, column, operation)]
0
+ def execute_grouped_calculation(operation, column_name, column, aggregate, aggregate_alias, options) #:nodoc:
0
+ group_attr = options[:group].to_s
0
+ association = reflect_on_association(group_attr.to_sym)
0
+ associated = association && association.macro == :belongs_to # only count belongs_to associations
0
+ group_field = (associated ? "#{options[:group]}_id" : options[:group]).to_s
0
+ group_alias = column_alias_for(group_field)
0
+ group_column = column_for group_field
0
+ sql = construct_calculation_sql(aggregate, aggregate_alias, options.merge(:group_field => group_field, :group_alias => group_alias))
0
+ calculated_data = connection.select_all(sql)
0
+ key_ids = calculated_data.collect { |row| row[group_alias] }
0
+ key_records = association.klass.base_class.find(key_ids)
0
+ key_records = key_records.inject({}) { |hsh, r| hsh.merge(r.id => r) }
0
+ calculated_data.inject(OrderedHash.new) do |all, row|
0
+ key = associated ? key_records[row[group_alias].to_i] : type_cast_calculated_value(row[group_alias], group_column)
0
+ value = row[aggregate_alias]
0
+ all << [key, type_cast_calculated_value(value, column, operation)]
0
- def validate_calculation_options(operation, options = {})
0
- if operation.to_s == 'count'
0
- options.assert_valid_keys(CALCULATIONS_OPTIONS + [:include])
0
- options.assert_valid_keys(CALCULATIONS_OPTIONS)
0
+ def validate_calculation_options(operation, options = {})
0
+ if operation.to_s == 'count'
0
+ options.assert_valid_keys(CALCULATIONS_OPTIONS + [:include])
0
+ options.assert_valid_keys(CALCULATIONS_OPTIONS)
0
- def select_aggregate(operation, column_name, options)
0
- "#{operation}(#{'DISTINCT ' if options[:distinct]}#{column_name})"
0
+ def select_aggregate(operation, column_name, options)
0
+ "#{operation}(#{'DISTINCT ' if options[:distinct]}#{column_name})"
0
- # converts a given key to the value that the database adapter returns as
0
- # users.id #=> users_id
0
- # count(distinct users.id) #=> count_distinct_users_id
0
- # count(*) #=> count_all
0
- def column_alias_for(*keys)
0
- keys.join(' ').downcase.gsub(/\*/, 'all').gsub(/\W+/, ' ').strip.gsub(/ +/, '_')
0
+ # converts a given key to the value that the database adapter returns as
0
+ # users.id #=> users_id
0
+ # count(distinct users.id) #=> count_distinct_users_id
0
+ # count(*) #=> count_all
0
+ def column_alias_for(*keys)
0
+ keys.join(' ').downcase.gsub(/\*/, 'all').gsub(/\W+/, ' ').strip.gsub(/ +/, '_')
0
- field_name = field.to_s.split('.').last
0
- columns.detect { |c| c.name.to_s == field_name }
0
+ field_name = field.to_s.split('.').last
0
+ columns.detect { |c| c.name.to_s == field_name }
0
- def type_cast_calculated_value(value, column, operation = nil)
0
- operation = operation.to_s.downcase
0
- when 'count' then value.to_i
0
- when 'avg' then value.to_f
0
- else column ? column.type_cast(value) : value
0
+ def type_cast_calculated_value(value, column, operation = nil)
0
+ operation = operation.to_s.downcase
0
+ when 'count' then value.to_i
0
+ when 'avg' then value.to_f
0
+ else column ? column.type_cast(value) : value
Comments
No one has commented yet.