diff options
Diffstat (limited to 'activerecord/lib/active_record/calculations.rb')
-rw-r--r-- | activerecord/lib/active_record/calculations.rb | 90 |
1 files changed, 9 insertions, 81 deletions
diff --git a/activerecord/lib/active_record/calculations.rb b/activerecord/lib/active_record/calculations.rb index cd7bd185c5..fc6cb793ab 100644 --- a/activerecord/lib/active_record/calculations.rb +++ b/activerecord/lib/active_record/calculations.rb @@ -2,8 +2,6 @@ module ActiveRecord module Calculations #:nodoc: extend ActiveSupport::Concern - CALCULATIONS_OPTIONS = [:conditions, :joins, :order, :select, :group, :having, :distinct, :limit, :offset, :include, :from] - module ClassMethods # Count operates using three different approaches. # @@ -46,19 +44,19 @@ module ActiveRecord def count(*args) case args.size when 0 - construct_calculation_arel({}, current_scoped_methods).count + construct_calculation_arel.count when 1 if args[0].is_a?(Hash) options = args[0] distinct = options.has_key?(:distinct) ? options.delete(:distinct) : false - construct_calculation_arel(options, current_scoped_methods).count(options[:select], :distinct => distinct) + construct_calculation_arel(options).count(options[:select], :distinct => distinct) else - construct_calculation_arel({}, current_scoped_methods).count(args[0]) + construct_calculation_arel.count(args[0]) end when 2 column_name, options = args distinct = options.has_key?(:distinct) ? options.delete(:distinct) : false - construct_calculation_arel(options, current_scoped_methods).count(column_name, :distinct => distinct) + construct_calculation_arel(options).count(column_name, :distinct => distinct) else raise ArgumentError, "Unexpected parameters passed to count(): #{args.inspect}" end @@ -141,87 +139,17 @@ module ActiveRecord # Person.minimum(:age, :having => 'min(age) > 17', :group => :last_name) # Selects the minimum age for any family without any minors # Person.sum("2 * age") def calculate(operation, column_name, options = {}) - construct_calculation_arel(options, current_scoped_methods).calculate(operation, column_name, options.slice(:distinct)) + construct_calculation_arel(options).calculate(operation, column_name, options.slice(:distinct)) rescue ThrowResult 0 end private - def validate_calculation_options(options = {}) - options.assert_valid_keys(CALCULATIONS_OPTIONS) - end - - def construct_calculation_arel(options = {}, merge_with_relation = nil) - validate_calculation_options(options) - options = options.except(:distinct) - - includes = merge_includes(merge_with_relation ? merge_with_relation.includes_values : [], options[:include]) - - if includes.any? - merge_with_joins = merge_with_relation ? merge_with_relation.joins_values : [] - joins = (merge_with_joins + Array.wrap(options[:joins])).uniq - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, includes, construct_join(joins)) - construct_calculation_arel_with_included_associations(options, join_dependency, merge_with_relation) - else - relation = active_relation. - joins(options[:joins]). - where(options[:conditions]). - order(options[:order]). - limit(options[:limit]). - offset(options[:offset]). - group(options[:group]). - having(options[:having]) - - if merge_with_relation - relation = merge_with_relation.except(:select, :order, :limit, :offset, :group, :from).merge(relation) - else - relation = relation.where(type_condition) if finder_needs_type_condition? - end - - from = merge_with_relation.from_value if merge_with_relation && merge_with_relation.from_value.present? - from = options[:from] if from.blank? && options[:from].present? - relation = relation.from(from) - - select = options[:select].presence || (merge_with_relation ? merge_with_relation.select_values.join(", ") : nil) - relation = relation.select(select) - - relation - end - end - - def construct_calculation_arel_with_included_associations(options, join_dependency, merge_with_relation = nil) - relation = active_relation - for association in join_dependency.join_associations - relation = association.join_relation(relation) - end - - if merge_with_relation - relation.joins_values = (merge_with_relation.joins_values + relation.joins_values).uniq - relation.where_values = merge_with_relation.where_values - - merge_limit = merge_with_relation.taken - else - relation = relation.where(type_condition) if finder_needs_type_condition? - end - - relation = relation.joins(options[:joins]). - select(column_aliases(join_dependency)). - group(options[:group]). - having(options[:having]). - order(options[:order]). - where(options[:conditions]). - from(options[:from]) - - - if !using_limitable_reflections?(join_dependency.reflections) && (merge_limit || options[:limit]) - relation = relation.where(construct_arel_limited_ids_condition(options, join_dependency)) - end - - relation = relation.limit(options[:limit] || merge_limit) if using_limitable_reflections?(join_dependency.reflections) - - relation - end + def construct_calculation_arel(options = {}) + relation = scoped.apply_finder_options(options.except(:distinct)) + (relation.eager_loading? || relation.includes_values.present?) ? relation.send(:construct_relation_for_association_calculations) : relation + end end end |