Skip to content

Readds the fix for #5667 and back ports the regression fix from #5718 #5898

Merged
merged 4 commits into from Apr 19, 2012
View
6 activerecord/CHANGELOG.md
@@ -1,3 +1,9 @@
+## Rails 3.2.4 (unreleased) ##
+
+* Association preloading shouldn't be affected by the current scoping.
+ This could cause infinite recursion and potentially other problems.
+ See GH #5667. *Jon Leighton*
+
## Rails 3.2.3 (unreleased) ##
* Added find_or_create_by_{attribute}! dynamic method. *Andrew White*
View
5 activerecord/lib/active_record/associations/preloader/association.rb
@@ -77,7 +77,7 @@ def associated_records_by_owner
# Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
# Make several smaller queries if necessary or make one query if the adapter supports it
sliced = owner_keys.each_slice(model.connection.in_clause_length || owner_keys.size)
- records = sliced.map { |slice| records_for(slice) }.flatten
+ records = sliced.map { |slice| records_for(slice).to_a }.flatten
end
# Each record may have multiple owners, and vice-versa
@@ -93,7 +93,8 @@ def associated_records_by_owner
end
def build_scope
- scope = klass.scoped
+ scope = klass.unscoped
+ scope.default_scoped = true
scope = scope.where(process_conditions(options[:conditions]))
scope = scope.where(process_conditions(preload_options[:conditions]))
View
7 activerecord/lib/active_record/base.rb
@@ -450,12 +450,12 @@ def arel_engine
private
def relation #:nodoc:
- @relation ||= Relation.new(self, arel_table)
+ relation ||= Relation.new(self, arel_table)
if finder_needs_type_condition?
- @relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
+ relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
else
- @relation
+ relation
end
end
end
@@ -489,7 +489,6 @@ def initialize(attributes = nil, options = {})
@marked_for_destruction = false
@previously_changed = {}
@changed_attributes = {}
- @relation = nil
ensure_proper_type
View
4 activerecord/lib/active_record/scoping/named.rb
@@ -34,7 +34,7 @@ def scoped(options = nil)
if current_scope
current_scope.clone
else
- scope = relation.clone
+ scope = relation
scope.default_scoped = true
scope
end
@@ -48,7 +48,7 @@ def scope_attributes # :nodoc:
if current_scope
current_scope.scope_for_create
else
- scope = relation.clone
+ scope = relation
scope.default_scoped = true
scope.scope_for_create
end
View
24 activerecord/test/cases/associations/eager_test.rb
@@ -1095,4 +1095,28 @@ def test_join_eager_with_nil_order_should_generate_valid_sql
Post.includes(:comments).order(nil).where(:comments => {:body => "Thank you for the welcome"}).first
end
end
+
+ def test_deep_including_through_habtm
+ posts = Post.find(:all, :include => {:categories => :categorizations}, :order => "posts.id")
+ assert_no_queries { assert_equal 2, posts[0].categories[0].categorizations.length }
+ assert_no_queries { assert_equal 1, posts[0].categories[1].categorizations.length }
+ assert_no_queries { assert_equal 2, posts[1].categories[0].categorizations.length }
+ end
+
+ test "scoping with a circular preload" do
+ assert_equal Comment.find(1), Comment.preload(:post => :comments).scoping { Comment.find(1) }
+ end
+
+ test "circular preload does not modify unscoped" do
+ expected = FirstPost.unscoped.find(2)
+ FirstPost.preload(:comments => :first_post).find(1)
+ assert_equal expected, FirstPost.unscoped.find(2)
+ end
+
+ test "preload ignores the scoping" do
+ assert_equal(
+ Comment.find(1).post,
+ Post.where('1 = 0').scoping { Comment.preload(:post).find(1).post }
+ )
+ end
end
View
2 activerecord/test/models/comment.rb
@@ -11,6 +11,8 @@ class Comment < ActiveRecord::Base
belongs_to :post, :counter_cache => true
has_many :ratings
+ belongs_to :first_post, :foreign_key => :post_id
+
has_many :children, :class_name => 'Comment', :foreign_key => :parent_id
belongs_to :parent, :class_name => 'Comment', :counter_cache => :children_count
Something went wrong with that request. Please try again.