aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/calculations.rb
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2010-01-14 13:36:33 +0530
committerPratik Naik <pratiknaik@gmail.com>2010-01-16 00:02:46 +0530
commitbed9179aa1496f6d28891cf515af0d7e515ebbab (patch)
treeb0c551489b45f93f66c0d726c55fe000b59803ea /activerecord/lib/active_record/calculations.rb
parent1c30ec23fef2479cd037945e57a74e5c89c9ece1 (diff)
downloadrails-bed9179aa1496f6d28891cf515af0d7e515ebbab.tar.gz
rails-bed9179aa1496f6d28891cf515af0d7e515ebbab.tar.bz2
rails-bed9179aa1496f6d28891cf515af0d7e515ebbab.zip
Make scopes use relations under the hood
Diffstat (limited to 'activerecord/lib/active_record/calculations.rb')
-rw-r--r--activerecord/lib/active_record/calculations.rb73
1 files changed, 49 insertions, 24 deletions
diff --git a/activerecord/lib/active_record/calculations.rb b/activerecord/lib/active_record/calculations.rb
index 20d287faeb..bbb5922e0e 100644
--- a/activerecord/lib/active_record/calculations.rb
+++ b/activerecord/lib/active_record/calculations.rb
@@ -46,19 +46,19 @@ module ActiveRecord
def count(*args)
case args.size
when 0
- construct_calculation_arel.count
+ construct_calculation_arel({}, current_scoped_methods).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).count(options[:select], :distinct => distinct)
+ construct_calculation_arel(options, current_scoped_methods).count(options[:select], :distinct => distinct)
else
- construct_calculation_arel.count(args[0])
+ construct_calculation_arel({}, current_scoped_methods).count(args[0])
end
when 2
column_name, options = args
distinct = options.has_key?(:distinct) ? options.delete(:distinct) : false
- construct_calculation_arel(options).count(column_name, :distinct => distinct)
+ construct_calculation_arel(options, current_scoped_methods).count(column_name, :distinct => distinct)
else
raise ArgumentError, "Unexpected parameters passed to count(): #{args.inspect}"
end
@@ -141,7 +141,7 @@ 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).calculate(operation, column_name, options.slice(:distinct))
+ construct_calculation_arel(options, current_scoped_methods).calculate(operation, column_name, options.slice(:distinct))
rescue ThrowResult
0
end
@@ -151,49 +151,74 @@ module ActiveRecord
options.assert_valid_keys(CALCULATIONS_OPTIONS)
end
- def construct_calculation_arel(options = {})
+ def construct_calculation_arel(options = {}, merge_with_relation = nil)
validate_calculation_options(options)
options = options.except(:distinct)
- scope = scope(:find)
- includes = merge_includes(scope ? scope[:include] : [], options[:include])
+ includes = merge_includes(merge_with_relation ? merge_with_relation.includes_values : [], options[:include])
if includes.any?
- join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, includes, construct_join(options[:joins], scope))
- construct_calculation_arel_with_included_associations(options, join_dependency)
+ 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, nil))
+ construct_calculation_arel_with_included_associations(options, join_dependency, merge_with_relation)
else
- active_relation.
- joins(construct_join(options[:joins], scope)).
- from((scope && scope[:from]) || options[:from]).
- where(construct_conditions(options[:conditions], scope)).
+ relation = active_relation.
+ joins(options[:joins]).
+ where(options[:conditions]).
order(options[:order]).
limit(options[:limit]).
offset(options[:offset]).
group(options[:group]).
- having(options[:having]).
- select(options[:select] || (scope && scope[:select]) || default_select(options[:joins] || (scope && scope[:joins])))
+ 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)
- scope = scope(:find)
-
+ 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
- relation = relation.joins(construct_join(options[:joins], scope)).
+ 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(construct_conditions(options[:conditions], scope)).
- from((scope && scope[:from]) || options[:from])
+ 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.where(construct_arel_limited_ids_condition(options, join_dependency)) if !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit])
- relation = relation.limit(construct_limit(options[:limit], scope)) if using_limitable_reflections?(join_dependency.reflections)
+ relation = relation.limit(options[:limit] || merge_limit) if using_limitable_reflections?(join_dependency.reflections)
relation
end