Changeset 8672
- Timestamp:
- 01/19/08 04:19:53 (4 months ago)
- Files:
-
- trunk/activerecord/CHANGELOG (modified) (1 diff)
- trunk/activerecord/lib/active_record.rb (modified) (2 diffs)
- trunk/activerecord/lib/active_record/association_preload.rb (added)
- trunk/activerecord/lib/active_record/associations.rb (modified) (1 diff)
- trunk/activerecord/lib/active_record/base.rb (modified) (1 diff)
- trunk/activerecord/test/cases/associations_test.rb (modified) (1 diff)
- trunk/activerecord/test/cases/associations/eager_test.rb (modified) (8 diffs)
- trunk/activerecord/test/cases/associations/join_model_test.rb (modified) (3 diffs)
- trunk/activerecord/test/models/post.rb (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/activerecord/CHANGELOG
r8671 r8672 1 1 *SVN* 2 3 * Introduce preload query strategy for eager :includes. #9640 [Frederick Cheung, Aleksey Kondratenko] 2 4 3 5 * Support aggregations in finder conditions. #10572 [Ryan Kinderman] trunk/activerecord/lib/active_record.rb
r7768 r8672 44 44 require 'active_record/reflection' 45 45 require 'active_record/associations' 46 require 'active_record/association_preload' 46 47 require 'active_record/aggregations' 47 48 require 'active_record/transactions' … … 64 65 include ActiveRecord::Timestamp 65 66 include ActiveRecord::Associations 67 include ActiveRecord::AssociationPreload 66 68 include ActiveRecord::Aggregations 67 69 include ActiveRecord::Transactions trunk/activerecord/lib/active_record/associations.rb
r8562 r8672 1366 1366 order = options[:order] 1367 1367 return false unless order 1368 order. scan(/([\.\w]+)\.\w+/).flatten.any? do |order_table_name|1368 order.to_s.scan(/([\.\w]+)\.\w+/).flatten.any? do |order_table_name| 1369 1369 order_table_name != table_name 1370 1370 end 1371 end 1372 1373 def references_eager_loaded_tables?(options) 1374 include_eager_order?(options) || include_eager_conditions?(options) 1371 1375 end 1372 1376 trunk/activerecord/lib/active_record/base.rb
r8671 r8672 1238 1238 1239 1239 def find_every(options) 1240 records = scoped?(:find, :include) || options[:include] ? 1241 find_with_associations(options) : 1242 find_by_sql(construct_finder_sql(options)) 1240 include_associations = merge_includes(scope(:find, :include), options[:include]) 1241 1242 if include_associations.any? && references_eager_loaded_tables?(options) 1243 records = find_with_associations(options) 1244 else 1245 records = find_by_sql(construct_finder_sql(options)) 1246 if include_associations.any? 1247 preload_associations(records, include_associations) 1248 end 1249 end 1243 1250 1244 1251 records.each { |record| record.readonly! } if options[:readonly] trunk/activerecord/test/cases/associations_test.rb
r8661 r8672 22 22 :computers 23 23 24 def test_include_with_order_works 25 assert_nothing_raised {Account.find(:first, :order => 'id', :include => :firm)} 26 assert_nothing_raised {Account.find(:first, :order => :id, :include => :firm)} 27 end 28 24 29 def test_bad_collection_keys 25 30 assert_raise(ArgumentError, 'ActiveRecord should have barked on bad collection keys') do trunk/activerecord/test/cases/associations/eager_test.rb
r8660 r8672 1 1 require 'abstract_unit' 2 2 require 'models/post' 3 require 'models/tagging' 3 4 require 'models/comment' 4 5 require 'models/author' … … 10 11 class EagerAssociationTest < ActiveSupport::TestCase 11 12 fixtures :posts, :comments, :authors, :categories, :categories_posts, 12 :companies, :accounts, :tags, : people, :readers13 :companies, :accounts, :tags, :taggings, :people, :readers 13 14 14 15 def test_loading_with_one_association … … 55 56 assert_equal 2, posts.first.categories.size 56 57 assert posts.first.comments.include?(comments(:greetings)) 58 end 59 60 def test_duplicate_middle_objects 61 comments = Comment.find :all, :conditions => 'post_id = 1', :include => [:post => :author] 62 assert_no_queries do 63 comments.each {|comment| comment.post.author.name} 64 end 57 65 end 58 66 … … 352 360 assert_equal posts(:thinking, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title), posts.id', :limit => 2, :offset => 1) 353 361 assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC, posts.id', :limit => 2, :offset => 1) 362 end 363 364 def test_preload_with_interpolation 365 assert_equal [comments(:greetings)], Post.find(posts(:welcome).id, :include => :comments_with_interpolated_conditions).comments_with_interpolated_conditions 366 end 367 368 def test_polymorphic_type_condition 369 post = Post.find(posts(:thinking).id, :include => :taggings) 370 assert post.taggings.include?(taggings(:thinking_general)) 371 post = SpecialPost.find(posts(:thinking).id, :include => :taggings) 372 assert post.taggings.include?(taggings(:thinking_general)) 354 373 end 355 374 … … 406 425 def test_preconfigured_includes_with_belongs_to 407 426 author = posts(:welcome).author_with_posts 408 assert_ equal 5, author.posts.size427 assert_no_queries {assert_equal 5, author.posts.size} 409 428 end 410 429 411 430 def test_preconfigured_includes_with_has_one 412 431 comment = posts(:sti_comments).very_special_comment_with_post 413 assert_ equal posts(:sti_comments), comment.post432 assert_no_queries {assert_equal posts(:sti_comments), comment.post} 414 433 end 415 434 … … 417 436 posts = authors(:david).posts_with_comments 418 437 one = posts.detect { |p| p.id == 1 } 419 assert_equal 5, posts.size 420 assert_equal 2, one.comments.size 438 assert_no_queries do 439 assert_equal 5, posts.size 440 assert_equal 2, one.comments.size 441 end 421 442 end 422 443 … … 424 445 posts = authors(:david).posts_with_categories 425 446 one = posts.detect { |p| p.id == 1 } 426 assert_equal 5, posts.size 427 assert_equal 2, one.categories.size 447 assert_no_queries do 448 assert_equal 5, posts.size 449 assert_equal 2, one.categories.size 450 end 428 451 end 429 452 … … 431 454 posts = authors(:david).posts_with_comments_and_categories 432 455 one = posts.detect { |p| p.id == 1 } 433 assert_equal 5, posts.size 434 assert_equal 2, one.comments.size 435 assert_equal 2, one.categories.size 456 assert_no_queries do 457 assert_equal 5, posts.size 458 assert_equal 2, one.comments.size 459 assert_equal 2, one.categories.size 460 end 436 461 end 437 462 trunk/activerecord/test/cases/associations/join_model_test.rb
r8661 r8672 318 318 end 319 319 assert_raise ActiveRecord::EagerLoadPolymorphicError do 320 assert_equal posts(:welcome, :thinking), tags(:general).taggings.find(:all, :include => :taggable )320 assert_equal posts(:welcome, :thinking), tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1') 321 321 end 322 322 end … … 332 332 assert_equal desired, tag_with_include.tagged_posts 333 333 end 334 assert_equal 4, tag_with_include.taggings.length 334 335 end 335 336 … … 547 548 end 548 549 550 def test_polymorphic_has_many 551 expected = taggings(:welcome_general) 552 p = Post.find(posts(:welcome).id, :include => :taggings) 553 assert_no_queries {assert p.taggings.include?(expected)} 554 assert posts(:welcome).taggings.include?(taggings(:welcome_general)) 555 end 556 557 def test_polymorphic_has_one 558 expected = posts(:welcome) 559 560 tagging = Tagging.find(taggings(:welcome_general).id, :include => :taggable) 561 assert_no_queries { assert_equal expected, tagging.taggable} 562 end 563 564 def test_polymorphic_belongs_to 565 p = Post.find(posts(:welcome).id, :include => {:taggings => :taggable}) 566 assert_no_queries {assert_equal posts(:welcome), p.taggings.first.taggable} 567 end 568 569 def test_preload_polymorphic_has_many_through 570 posts = Post.find(:all, :order => 'posts.id') 571 posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id') 572 assert_equal posts.length, posts_with_tags.length 573 posts.length.times do |i| 574 assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length } 575 end 576 end 577 578 def test_preload_polymorph_many_types 579 taggings = Tagging.find :all, :include => :taggable, :conditions => ['taggable_type != ?', 'FakeModel'] 580 assert_no_queries do 581 taggings.first.taggable.id 582 taggings[1].taggable.id 583 end 584 585 taggables = taggings.map(&:taggable) 586 assert taggables.include?(items(:dvd)) 587 assert taggables.include?(posts(:welcome)) 588 end 589 590 def test_preload_polymorphic_has_many 591 posts = Post.find(:all, :order => 'posts.id') 592 posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id') 593 assert_equal posts.length, posts_with_taggings.length 594 posts.length.times do |i| 595 assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length } 596 end 597 end 598 599 def test_belongs_to_shared_parent 600 comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 1') 601 assert_no_queries do 602 assert_equal comments.first.post, comments[1].post 603 end 604 end 605 549 606 private 550 607 # create dynamic Post models to allow different dependency options trunk/activerecord/test/models/post.rb
r8657 r8672 13 13 end 14 14 end 15 16 has_many :comments_with_interpolated_conditions, :class_name => 'Comment', 17 :conditions => ['#{"#{aliased_table_name}." rescue ""}body = ?', 'Thank you for the welcome'] 15 18 16 19 has_one :very_special_comment