aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/association_collection.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/associations/association_collection.rb')
-rw-r--r--activerecord/lib/active_record/associations/association_collection.rb66
1 files changed, 29 insertions, 37 deletions
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index cb2d9e0a79..896e18af01 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -19,11 +19,6 @@ module ActiveRecord
# If you need to work on all current children, new and existing records,
# +load_target+ and the +loaded+ flag are your friends.
class AssociationCollection < AssociationProxy #:nodoc:
- def initialize(owner, reflection)
- super
- construct_sql
- end
-
delegate :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :to => :scoped
def select(select = nil)
@@ -36,7 +31,7 @@ module ActiveRecord
end
def scoped
- with_scope(construct_scope) { @reflection.klass.scoped }
+ with_scope(@scope) { @reflection.klass.scoped }
end
def find(*args)
@@ -58,9 +53,7 @@ module ActiveRecord
merge_options_from_reflection!(options)
construct_find_options!(options)
- find_scope = construct_scope[:find].slice(:conditions, :order)
-
- with_scope(:find => find_scope) do
+ with_scope(:find => @scope[:find].slice(:conditions, :order)) do
relation = @reflection.klass.send(:construct_finder_arel, options, @reflection.klass.send(:current_scoped_methods))
case args.first
@@ -178,17 +171,18 @@ module ActiveRecord
end
end
- # Count all records using SQL. If the +:counter_sql+ option is set for the association, it will
- # be used for the query. If no +:counter_sql+ was supplied, but +:finder_sql+ was set, the
- # descendant's +construct_sql+ method will have set :counter_sql automatically.
- # Otherwise, construct options and pass them with scope to the target class's +count+.
+ # Count all records using SQL. If the +:counter_sql+ or +:finder_sql+ option is set for the
+ # association, it will be used for the query. Otherwise, construct options and pass them with
+ # scope to the target class's +count+.
def count(column_name = nil, options = {})
column_name, options = nil, column_name if column_name.is_a?(Hash)
- if @reflection.options[:counter_sql] && !options.blank?
- raise ArgumentError, "If finder_sql/counter_sql is used then options cannot be passed"
- elsif @reflection.options[:counter_sql]
- @reflection.klass.count_by_sql(@counter_sql)
+ if @reflection.options[:counter_sql] || @reflection.options[:finder_sql]
+ unless options.blank?
+ raise ArgumentError, "If finder_sql/counter_sql is used then options cannot be passed"
+ end
+
+ @reflection.klass.count_by_sql(custom_counter_sql)
else
if @reflection.options[:uniq]
@@ -197,7 +191,7 @@ module ActiveRecord
options.merge!(:distinct => true)
end
- value = @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.count(column_name, options) }
+ value = @reflection.klass.send(:with_scope, @scope) { @reflection.klass.count(column_name, options) }
limit = @reflection.options[:limit]
offset = @reflection.options[:offset]
@@ -377,18 +371,6 @@ module ActiveRecord
def construct_find_options!(options)
end
- def construct_counter_sql
- if @reflection.options[:counter_sql]
- @counter_sql = interpolate_sql(@reflection.options[:counter_sql])
- elsif @reflection.options[:finder_sql]
- # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */
- @reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT\b(\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
- @counter_sql = interpolate_sql(@reflection.options[:counter_sql])
- else
- @counter_sql = @finder_sql
- end
- end
-
def load_target
if !@owner.new_record? || foreign_key_present
begin
@@ -434,9 +416,9 @@ module ActiveRecord
elsif @reflection.klass.scopes[method]
@_named_scopes_cache ||= {}
@_named_scopes_cache[method] ||= {}
- @_named_scopes_cache[method][args] ||= with_scope(construct_scope) { @reflection.klass.send(method, *args) }
+ @_named_scopes_cache[method][args] ||= with_scope(@scope) { @reflection.klass.send(method, *args) }
else
- with_scope(construct_scope) do
+ with_scope(@scope) do
if block_given?
@reflection.klass.send(method, *args) { |*block_args| yield(*block_args) }
else
@@ -446,9 +428,19 @@ module ActiveRecord
end
end
- # overloaded in derived Association classes to provide useful scoping depending on association type.
- def construct_scope
- {}
+ def custom_counter_sql
+ if @reflection.options[:counter_sql]
+ counter_sql = @reflection.options[:counter_sql]
+ else
+ # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */
+ counter_sql = @reflection.options[:finder_sql].sub(/SELECT\b(\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" }
+ end
+
+ interpolate_sql(counter_sql)
+ end
+
+ def custom_finder_sql
+ interpolate_sql(@reflection.options[:finder_sql])
end
def reset_target!
@@ -462,7 +454,7 @@ module ActiveRecord
def find_target
records =
if @reflection.options[:finder_sql]
- @reflection.klass.find_by_sql(@finder_sql)
+ @reflection.klass.find_by_sql(custom_finder_sql)
else
find(:all)
end
@@ -494,7 +486,7 @@ module ActiveRecord
ensure_owner_is_not_new
scoped_where = scoped.where_values_hash
- create_scope = scoped_where ? construct_scope[:create].merge(scoped_where) : construct_scope[:create]
+ create_scope = scoped_where ? @scope[:create].merge(scoped_where) : @scope[:create]
record = @reflection.klass.send(:with_scope, :create => create_scope) do
@reflection.build_association(attrs)
end