From b689834bcf2730353d066277f43047f10abb8d30 Mon Sep 17 00:00:00 2001 From: Bodaniel Jeanes Date: Sun, 26 Sep 2010 22:17:18 +1000 Subject: Initial nested_has_many_through support [#1152] --- .../test/cases/associations/join_model_test.rb | 8 ---- .../nested_has_many_through_associations_test.rb | 43 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 activerecord/test/cases/associations/nested_has_many_through_associations_test.rb (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index f131dc01f6..0b1a3db1e4 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -394,14 +394,6 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase end end - def test_has_many_through_has_many_through - assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tags } - end - - def test_has_many_through_habtm - assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).post_categories } - end - def test_eager_load_has_many_through_has_many author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id' SpecialComment.new; VerySpecialComment.new diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb new file mode 100644 index 0000000000..36de709ffc --- /dev/null +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -0,0 +1,43 @@ +require "cases/helper" +require 'models/author' +require 'models/post' +require 'models/person' +require 'models/reference' +require 'models/job' +require 'models/reader' +require 'models/comment' +require 'models/tag' +require 'models/tagging' +require 'models/owner' +require 'models/pet' +require 'models/toy' +require 'models/contract' +require 'models/company' +require 'models/developer' +require 'models/subscriber' +require 'models/book' +require 'models/subscription' + +class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase + fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings + + def test_has_many_through_a_has_many_through_association_on_source_reflection + author = authors(:david) + assert_equal [tags(:general), tags(:general)], author.tags + end + + def test_has_many_through_a_has_many_through_association_on_through_reflection + author = authors(:david) + assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], author.subscribers + end + + def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection + author = authors(:david) + assert_equal [tags(:general)], author.distinct_tags + end + + def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection + author = authors(:david) + assert_equal [subscribers(:first), subscribers(:second)], author.distinct_subscribers + end +end \ No newline at end of file -- cgit v1.2.3 From 4f69a61107d9d59f96bf249ef077483e90babe72 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 1 Oct 2010 13:10:41 +0100 Subject: Started implementing nested :through associations by using the existing structure of ThroughAssociationScope rather than layering a module over the top --- .../nested_has_many_through_associations_test.rb | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 36de709ffc..539e6e000a 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -21,23 +21,23 @@ require 'models/subscription' class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings - def test_has_many_through_a_has_many_through_association_on_source_reflection - author = authors(:david) - assert_equal [tags(:general), tags(:general)], author.tags - end +# def test_has_many_through_a_has_many_through_association_on_source_reflection +# author = authors(:david) +# assert_equal [tags(:general), tags(:general)], author.tags +# end def test_has_many_through_a_has_many_through_association_on_through_reflection author = authors(:david) assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], author.subscribers end - def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection - author = authors(:david) - assert_equal [tags(:general)], author.distinct_tags - end +# def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection +# author = authors(:david) +# assert_equal [tags(:general)], author.distinct_tags +# end - def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection - author = authors(:david) - assert_equal [subscribers(:first), subscribers(:second)], author.distinct_subscribers - end -end \ No newline at end of file +# def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection +# author = authors(:david) +# assert_equal [subscribers(:first), subscribers(:second)], author.distinct_subscribers +# end +end -- cgit v1.2.3 From 34ee586e993ad9e466b81f376fa92feb5d312b4c Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sat, 2 Oct 2010 18:50:17 +0100 Subject: Integrate nested support into ThroughAssociationScope, using my concept of generating a 'chain' of reflections to be joined. It seems to work at the moment, all existing tests are passing. There may be further complications as we add more test cases for nested associations, though. --- .../nested_has_many_through_associations_test.rb | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 539e6e000a..938643b1b3 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -21,23 +21,23 @@ require 'models/subscription' class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings -# def test_has_many_through_a_has_many_through_association_on_source_reflection -# author = authors(:david) -# assert_equal [tags(:general), tags(:general)], author.tags -# end + def test_has_many_through_a_has_many_through_association_on_source_reflection + author = authors(:david) + assert_equal [tags(:general), tags(:general)], author.tags + end def test_has_many_through_a_has_many_through_association_on_through_reflection author = authors(:david) assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], author.subscribers end -# def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection -# author = authors(:david) -# assert_equal [tags(:general)], author.distinct_tags -# end + def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection + author = authors(:david) + assert_equal [tags(:general)], author.distinct_tags + end -# def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection -# author = authors(:david) -# assert_equal [subscribers(:first), subscribers(:second)], author.distinct_subscribers -# end + def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection + author = authors(:david) + assert_equal [subscribers(:first), subscribers(:second)], author.distinct_subscribers + end end -- cgit v1.2.3 From a34391c3b495bad268204bdf4f6b3483a61abcd5 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sat, 2 Oct 2010 21:45:46 +0100 Subject: Add support for table aliasing, with a test that needs aliasing in order to work correctly. This test incidentally provides a more complicated test case (4 inner joins, 2 using polymorphism). --- .../cases/associations/nested_has_many_through_associations_test.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 938643b1b3..925a9598fb 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -40,4 +40,9 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase author = authors(:david) assert_equal [subscribers(:first), subscribers(:second)], author.distinct_subscribers end + + def test_nested_has_many_through_with_a_table_referenced_multiple_times + author = authors(:bob) + assert_equal [posts(:misc_by_bob), posts(:misc_by_mary)], author.similar_posts.sort_by(&:id) + end end -- cgit v1.2.3 From 43711083dd34252877bab9df43d3db0fd42feeb2 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 3 Oct 2010 11:56:32 +0100 Subject: Fix the tests (I have actually verified that these are also the 'right' fixes, rather than just making the tests pass again) --- .../cases/associations/cascaded_eager_loading_test.rb | 18 +++++++++--------- activerecord/test/cases/associations/eager_test.rb | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index b93e49613d..8bb8f3e359 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -13,17 +13,17 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase def test_eager_association_loading_with_cascaded_two_levels authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id") - assert_equal 2, authors.size + assert_equal 3, authors.size assert_equal 5, authors[0].posts.size - assert_equal 1, authors[1].posts.size + assert_equal 2, authors[1].posts.size assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} end def test_eager_association_loading_with_cascaded_two_levels_and_one_level authors = Author.find(:all, :include=>[{:posts=>:comments}, :categorizations], :order=>"authors.id") - assert_equal 2, authors.size + assert_equal 3, authors.size assert_equal 5, authors[0].posts.size - assert_equal 1, authors[1].posts.size + assert_equal 2, authors[1].posts.size assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} assert_equal 1, authors[0].categorizations.size assert_equal 2, authors[1].categorizations.size @@ -54,15 +54,15 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase def test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations authors = Author.find(:all, :include=>{:posts=>[:comments, :categorizations]}, :order=>"authors.id") - assert_equal 2, authors.size + assert_equal 3, authors.size assert_equal 5, authors[0].posts.size - assert_equal 1, authors[1].posts.size + assert_equal 2, authors[1].posts.size assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} end def test_eager_association_loading_with_cascaded_two_levels_and_self_table_reference authors = Author.find(:all, :include=>{:posts=>[:comments, :author]}, :order=>"authors.id") - assert_equal 2, authors.size + assert_equal 3, authors.size assert_equal 5, authors[0].posts.size assert_equal authors(:david).name, authors[0].name assert_equal [authors(:david).name], authors[0].posts.collect{|post| post.author.name}.uniq @@ -130,9 +130,9 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase def test_eager_association_loading_where_first_level_returns_nil authors = Author.find(:all, :include => {:post_about_thinking => :comments}, :order => 'authors.id DESC') - assert_equal [authors(:mary), authors(:david)], authors + assert_equal [authors(:bob), authors(:mary), authors(:david)], authors assert_no_queries do - authors[1].post_about_thinking.comments.first + authors[2].post_about_thinking.comments.first end end end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 40859d425f..1669c4d5f4 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -53,8 +53,8 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_with_ordering list = Post.find(:all, :include => :comments, :order => "posts.id DESC") - [:eager_other, :sti_habtm, :sti_post_and_comments, :sti_comments, - :authorless, :thinking, :welcome + [:misc_by_mary, :misc_by_bob, :eager_other, :sti_habtm, :sti_post_and_comments, + :sti_comments, :authorless, :thinking, :welcome ].each_with_index do |post, index| assert_equal posts(post), list[index] end -- cgit v1.2.3 From 3cc35633872a0072764d8edb20f1fc4e14adf729 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 5 Oct 2010 20:20:27 +0100 Subject: A failing test for a nested has many through association loaded via Foo.joins(:bar) --- .../cases/associations/nested_has_many_through_associations_test.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 925a9598fb..a5d3f27702 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -45,4 +45,10 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase author = authors(:bob) assert_equal [posts(:misc_by_bob), posts(:misc_by_mary)], author.similar_posts.sort_by(&:id) end + + def test_nested_has_many_through_as_a_join + # All authors with subscribers where one of the subscribers' nick is 'alterself' + authors = Author.joins(:subscribers).where('subscribers.nick' => 'alterself') + assert_equal [authors(:david)], authors + end end -- cgit v1.2.3 From f2b41914d6be935182d37e0c0d491352ac3de043 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Wed, 6 Oct 2010 12:06:51 +0100 Subject: Refactoring JoinDependency and friends. This improves the code (IMO) including adding some explanatory comments, but more importantly structures it in such a way as to allow a JoinAssociation to produce an arbitrary number of actual joins, which will be necessary for nested has many through support. Also added 3 tests covering functionality which existed but was not previously covered. --- .../associations/cascaded_eager_loading_test.rb | 8 ++++---- activerecord/test/cases/associations/eager_test.rb | 8 ++++---- .../associations/inner_join_association_test.rb | 24 +++++++++++++++++++++- .../test/cases/associations/join_model_test.rb | 4 ++-- 4 files changed, 33 insertions(+), 11 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index 8bb8f3e359..0e9c8a2639 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -16,7 +16,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase assert_equal 3, authors.size assert_equal 5, authors[0].posts.size assert_equal 2, authors[1].posts.size - assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} + assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} end def test_eager_association_loading_with_cascaded_two_levels_and_one_level @@ -24,7 +24,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase assert_equal 3, authors.size assert_equal 5, authors[0].posts.size assert_equal 2, authors[1].posts.size - assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} + assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} assert_equal 1, authors[0].categorizations.size assert_equal 2, authors[1].categorizations.size end @@ -35,7 +35,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase end authors = Author.joins(:posts).eager_load(:comments).where(:posts => {:taggings_count => 1}).all assert_equal 1, assert_no_queries { authors.size } - assert_equal 9, assert_no_queries { authors[0].comments.size } + assert_equal 10, assert_no_queries { authors[0].comments.size } end def test_eager_association_loading_grafts_stashed_associations_to_correct_parent @@ -57,7 +57,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase assert_equal 3, authors.size assert_equal 5, authors[0].posts.size assert_equal 2, authors[1].posts.size - assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} + assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} end def test_eager_association_loading_with_cascaded_two_levels_and_self_table_reference diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 1669c4d5f4..2ff0714e9f 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -174,7 +174,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_association_loading_with_belongs_to comments = Comment.find(:all, :include => :post) - assert_equal 10, comments.length + assert_equal 11, comments.length titles = comments.map { |c| c.post.title } assert titles.include?(posts(:welcome).title) assert titles.include?(posts(:sti_post_and_comments).title) @@ -532,7 +532,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_has_many_with_association_inheritance post = Post.find(4, :include => [ :special_comments ]) post.special_comments.each do |special_comment| - assert_equal "SpecialComment", special_comment.class.to_s + assert special_comment.is_a?(SpecialComment) end end @@ -726,8 +726,8 @@ class EagerAssociationTest < ActiveRecord::TestCase posts = assert_queries(2) do Post.find(:all, :joins => :comments, :include => :author, :order => 'comments.id DESC') end - assert_equal posts(:eager_other), posts[0] - assert_equal authors(:mary), assert_no_queries { posts[0].author} + assert_equal posts(:eager_other), posts[1] + assert_equal authors(:mary), assert_no_queries { posts[1].author} end def test_eager_loading_with_conditions_on_joined_table_preloads diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index 4ba867dc7c..780eabc443 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -4,9 +4,12 @@ require 'models/comment' require 'models/author' require 'models/category' require 'models/categorization' +require 'models/tagging' +require 'models/tag' class InnerJoinAssociationTest < ActiveRecord::TestCase - fixtures :authors, :posts, :comments, :categories, :categories_posts, :categorizations + fixtures :authors, :posts, :comments, :categories, :categories_posts, :categorizations, + :taggings, :tags def test_construct_finder_sql_applies_aliases_tables_on_association_conditions result = Author.joins(:thinking_posts, :welcome_posts).to_a @@ -62,4 +65,23 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase authors_with_welcoming_post_titles = Author.calculate(:count, 'authors.id', :joins => :posts, :distinct => true, :conditions => "posts.title like 'Welcome%'") assert_equal real_count, authors_with_welcoming_post_titles, "inner join and conditions should have only returned authors posting titles starting with 'Welcome'" end + + def test_find_with_sti_join + scope = Post.joins(:special_comments).where(:id => posts(:sti_comments).id) + + # The join should match SpecialComment and its subclasses only + assert scope.where("comments.type" => "Comment").empty? + assert !scope.where("comments.type" => "SpecialComment").empty? + assert !scope.where("comments.type" => "SubSpecialComment").empty? + end + + def test_find_with_conditions_on_reflection + assert !posts(:welcome).comments.empty? + assert Post.joins(:nonexistant_comments).where(:id => posts(:welcome).id).empty? # [sic!] + end + + def test_find_with_conditions_on_through_reflection + assert !posts(:welcome).tags.empty? + assert Post.joins(:misc_tags).where(:id => posts(:welcome).id).empty? + end end diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index 0b1a3db1e4..4b7a8b494d 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -398,7 +398,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id' SpecialComment.new; VerySpecialComment.new assert_no_queries do - assert_equal [1,2,3,5,6,7,8,9,10], author.comments.collect(&:id) + assert_equal [1,2,3,5,6,7,8,9,10,12], author.comments.collect(&:id) end end @@ -500,7 +500,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase def test_has_many_through_collection_size_doesnt_load_target_if_not_loaded author = authors(:david) - assert_equal 9, author.comments.size + assert_equal 10, author.comments.size assert !author.comments.loaded? end -- cgit v1.2.3 From ab5a9335020eff0da35b62b86a62ed8587a4d598 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sat, 9 Oct 2010 22:00:33 +0100 Subject: Add support for nested through associations in JoinAssociation. Hence Foo.joins(:bar) will work for through associations. There is some duplicated code now, which will be refactored. --- .../nested_has_many_through_associations_test.rb | 59 ++++++++++++++++++++-- 1 file changed, 54 insertions(+), 5 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index a5d3f27702..ba75b70941 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -17,18 +17,37 @@ require 'models/developer' require 'models/subscriber' require 'models/book' require 'models/subscription' +require 'models/rating' + +# NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which +# are just one level deep. But it's all the same thing really, as the "nested" code is being +# written in a generic way which applies to "non-nested" HMT associations too. So let's just shove +# all useful tests in here for now and then work out where they ought to live properly later. class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase - fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings + fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, + :people, :readers, :references, :jobs, :ratings, :comments def test_has_many_through_a_has_many_through_association_on_source_reflection author = authors(:david) assert_equal [tags(:general), tags(:general)], author.tags + + # Only David has a Post tagged with General + authors = Author.joins(:tags).where('tags.id' => tags(:general).id) + assert_equal [authors(:david)], authors.uniq + + # This ensures that the polymorphism of taggings is being observed correctly + authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel') + assert authors.empty? end def test_has_many_through_a_has_many_through_association_on_through_reflection author = authors(:david) assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], author.subscribers + + # All authors with subscribers where one of the subscribers' nick is 'alterself' + authors = Author.joins(:subscribers).where('subscribers.nick' => 'alterself') + assert_equal [authors(:david)], authors end def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection @@ -44,11 +63,41 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_nested_has_many_through_with_a_table_referenced_multiple_times author = authors(:bob) assert_equal [posts(:misc_by_bob), posts(:misc_by_mary)], author.similar_posts.sort_by(&:id) + + # Mary and Bob both have posts in misc, but they are the only ones. + authors = Author.joins(:similar_posts).where('posts.id' => posts(:misc_by_bob).id) + assert_equal [authors(:mary), authors(:bob)], authors.uniq.sort_by(&:id) + + # Check the polymorphism of taggings is being observed correctly (in both joins) + authors = Author.joins(:similar_posts).where('taggings.taggable_type' => 'FakeModel') + assert authors.empty? + authors = Author.joins(:similar_posts).where('taggings_authors_join.taggable_type' => 'FakeModel') + assert authors.empty? end - def test_nested_has_many_through_as_a_join - # All authors with subscribers where one of the subscribers' nick is 'alterself' - authors = Author.joins(:subscribers).where('subscribers.nick' => 'alterself') - assert_equal [authors(:david)], authors + def test_has_many_through_with_foreign_key_option_on_through_reflection + assert_equal [posts(:welcome), posts(:authorless)], people(:david).agents_posts + assert_equal [authors(:david)], references(:david_unicyclist).agents_posts_authors + + references = Reference.joins(:agents_posts_authors).where('authors.id' => authors(:david).id) + assert_equal [references(:david_unicyclist)], references + end + + def test_has_many_through_with_foreign_key_option_on_source_reflection + assert_equal [people(:michael), people(:susan)], jobs(:unicyclist).agents + + jobs = Job.joins(:agents) + assert_equal [jobs(:unicyclist), jobs(:unicyclist)], jobs + end + + def test_has_many_through_with_sti_on_through_reflection + ratings = posts(:sti_comments).special_comments_ratings.sort_by(&:id) + assert_equal [ratings(:special_comment_rating), ratings(:sub_special_comment_rating)], ratings + + # Ensure STI is respected in the join + scope = Post.joins(:special_comments_ratings).where(:id => posts(:sti_comments).id) + assert scope.where("comments.type" => "Comment").empty? + assert !scope.where("comments.type" => "SpecialComment").empty? + assert !scope.where("comments.type" => "SubSpecialComment").empty? end end -- cgit v1.2.3 From 7aea695815821df332913bae4b47714a525009a3 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 12 Oct 2010 13:33:51 +0100 Subject: A load of tests that need to be written --- .../nested_has_many_through_associations_test.rb | 63 ++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index ba75b70941..8a4ab627bb 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -28,6 +28,26 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, :people, :readers, :references, :jobs, :ratings, :comments + # Through associations can either use the has_many or has_one macros. + # + # has_many + # - Source reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many + # - Through reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many + # + # has_one + # - Source reflection can be has_one or belongs_to + # - Through reflection can be has_one or belongs_to + # + # Additionally, the source reflection and/or through reflection may be subject to + # polymorphism and/or STI. + # + # When testing these, we need to make sure it works via loading the association directly, or + # joining the association, or including the association. We also need to ensure that associations + # are readonly where relevant. + + # has_many through + # Source: has_many through + # Through: has_many def test_has_many_through_a_has_many_through_association_on_source_reflection author = authors(:david) assert_equal [tags(:general), tags(:general)], author.tags @@ -41,6 +61,9 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert authors.empty? end + # has_many through + # Source: has_many + # Through: has_many through def test_has_many_through_a_has_many_through_association_on_through_reflection author = authors(:david) assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], author.subscribers @@ -49,6 +72,46 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase authors = Author.joins(:subscribers).where('subscribers.nick' => 'alterself') assert_equal [authors(:david)], authors end + + # TODO: has_many through + # Source: has_one through + # Through: has_one + + # TODO: has_many through + # Source: has_one + # Through: has_one through + + # TODO: has_many through + # Source: has_many through + # Through: has_one + + # TODO: has_many through + # Source: has_many + # Through: has_one through + + # TODO: has_many through + # Source: has_and_belongs_to_many + # Through: has_many + + # TODO: has_many through + # Source: has_many + # Through: has_and_belongs_to_many + + # TODO: has_many through + # Source: belongs_to + # Through: has_many through + + # TODO: has_many through + # Source: has_many through + # Through: belongs_to + + # TODO: has_one through + # Source: has_one through + # Through: has_one + + # TODO: has_one through + # Source: belongs_to + # Through: has_one through def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection author = authors(:david) -- cgit v1.2.3 From 1777600e6e11e553ad97b7bc89e4b19e992eb3d3 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 12 Oct 2010 16:40:24 +0100 Subject: Support has_one through assocs as the source association --- .../nested_has_many_through_associations_test.rb | 35 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 8a4ab627bb..4fab426696 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -18,6 +18,9 @@ require 'models/subscriber' require 'models/book' require 'models/subscription' require 'models/rating' +require 'models/member' +require 'models/member_detail' +require 'models/member_type' # NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which # are just one level deep. But it's all the same thing really, as the "nested" code is being @@ -26,7 +29,8 @@ require 'models/rating' class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, - :people, :readers, :references, :jobs, :ratings, :comments + :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, + :member_types # Through associations can either use the has_many or has_one macros. # @@ -56,6 +60,9 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase authors = Author.joins(:tags).where('tags.id' => tags(:general).id) assert_equal [authors(:david)], authors.uniq + authors = Author.includes(:tags) + assert_equal [tags(:general), tags(:general)], authors.first.tags + # This ensures that the polymorphism of taggings is being observed correctly authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel') assert authors.empty? @@ -71,11 +78,24 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # All authors with subscribers where one of the subscribers' nick is 'alterself' authors = Author.joins(:subscribers).where('subscribers.nick' => 'alterself') assert_equal [authors(:david)], authors + + # TODO: Make this work + # authors = Author.includes(:subscribers) + # assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], authors.first.subscribers end - # TODO: has_many through + # has_many through # Source: has_one through # Through: has_one + def test_has_many_through_has_one_with_has_one_through_source_reflection + assert_equal [member_types(:founding)], members(:groucho).nested_member_types + + members = Member.joins(:nested_member_types).where('member_types.id' => member_types(:founding).id) + assert_equal [members(:groucho)], members + + members = Member.includes(:nested_member_types) + assert_equal [member_types(:founding)], members.first.nested_member_types + end # TODO: has_many through # Source: has_one @@ -105,9 +125,18 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # Source: has_many through # Through: belongs_to - # TODO: has_one through + # has_one through # Source: has_one through # Through: has_one + def test_has_one_through_has_one_with_has_one_through_source_reflection + assert_equal member_types(:founding), members(:groucho).nested_member_type + + members = Member.joins(:nested_member_type).where('member_types.id' => member_types(:founding).id) + assert_equal [members(:groucho)], members + + members = Member.includes(:nested_member_type) + assert_equal member_types(:founding), members.first.nested_member_type + end # TODO: has_one through # Source: belongs_to -- cgit v1.2.3 From 6a016a551109ed2ef78fff8f74aef6b1f4ae96a9 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 12 Oct 2010 16:53:22 +0100 Subject: Add test_has_many_through_has_one_through --- .../nested_has_many_through_associations_test.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 4fab426696..c1e8a4b1bf 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -21,6 +21,8 @@ require 'models/rating' require 'models/member' require 'models/member_detail' require 'models/member_type' +require 'models/sponsor' +require 'models/club' # NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which # are just one level deep. But it's all the same thing really, as the "nested" code is being @@ -30,7 +32,7 @@ require 'models/member_type' class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, - :member_types + :member_types, :sponsors, :clubs # Through associations can either use the has_many or has_one macros. # @@ -97,9 +99,19 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [member_types(:founding)], members.first.nested_member_types end - # TODO: has_many through + # has_many through # Source: has_one # Through: has_one through + def test_has_many_through_has_one_through + assert_equal [sponsors(:moustache_club_sponsor_for_groucho)], members(:groucho).nested_sponsors + + members = Member.joins(:nested_sponsors).where('sponsors.id' => sponsors(:moustache_club_sponsor_for_groucho).id) + assert_equal [members(:groucho)], members + + # TODO: Make this work + # members = Member.includes(:nested_sponsors) + # assert_equal [sponsors(:moustache_club_sponsor_for_groucho)], members.first.nested_sponsors + end # TODO: has_many through # Source: has_many through -- cgit v1.2.3 From 61073861856110b4a842a4d5e1033698fd52901f Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 12 Oct 2010 16:54:43 +0100 Subject: Rename some tests for consistency --- .../cases/associations/nested_has_many_through_associations_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index c1e8a4b1bf..bc0fb8582d 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -54,7 +54,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # has_many through # Source: has_many through # Through: has_many - def test_has_many_through_a_has_many_through_association_on_source_reflection + def test_has_many_through_has_many_with_has_many_through_source_reflection author = authors(:david) assert_equal [tags(:general), tags(:general)], author.tags @@ -73,7 +73,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # has_many through # Source: has_many # Through: has_many through - def test_has_many_through_a_has_many_through_association_on_through_reflection + def test_has_many_through_has_many_through_with_has_many_source_reflection author = authors(:david) assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], author.subscribers @@ -102,7 +102,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # has_many through # Source: has_one # Through: has_one through - def test_has_many_through_has_one_through + def test_has_many_through_has_one_through_with_has_one_source_reflection assert_equal [sponsors(:moustache_club_sponsor_for_groucho)], members(:groucho).nested_sponsors members = Member.joins(:nested_sponsors).where('sponsors.id' => sponsors(:moustache_club_sponsor_for_groucho).id) -- cgit v1.2.3 From dc39aceb94fa810f8d7e263c0293f325fbf9a109 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 12 Oct 2010 17:27:10 +0100 Subject: Adding test_has_many_through_has_one_with_has_many_through_source_reflection and modifying ThroughAssociationScope to make it work correctly. --- .../nested_has_many_through_associations_test.rb | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index bc0fb8582d..4b5ce6313a 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -23,6 +23,7 @@ require 'models/member_detail' require 'models/member_type' require 'models/sponsor' require 'models/club' +require 'models/organization' # NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which # are just one level deep. But it's all the same thing really, as the "nested" code is being @@ -32,7 +33,7 @@ require 'models/club' class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, - :member_types, :sponsors, :clubs + :member_types, :sponsors, :clubs, :organizations # Through associations can either use the has_many or has_one macros. # @@ -113,9 +114,25 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # assert_equal [sponsors(:moustache_club_sponsor_for_groucho)], members.first.nested_sponsors end - # TODO: has_many through + # has_many through # Source: has_many through # Through: has_one + def test_has_many_through_has_one_with_has_many_through_source_reflection + assert_equal [member_details(:groucho), member_details(:some_other_guy)], + members(:groucho).organization_member_details + + members = Member.joins(:organization_member_details). + where('member_details.id' => member_details(:groucho).id) + assert_equal [members(:groucho), members(:some_other_guy)], members + + members = Member.joins(:organization_member_details). + where('member_details.id' => 9) + assert members.empty? + + members = Member.includes(:organization_member_details) + assert_equal [member_details(:groucho), member_details(:some_other_guy)], + members.first.organization_member_details + end # TODO: has_many through # Source: has_many -- cgit v1.2.3 From 56064aa4b014233ae54413628679b7f7fa5d6f77 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 12 Oct 2010 17:32:52 +0100 Subject: Add test_has_many_through_has_one_through_with_has_many_source_reflection --- .../nested_has_many_through_associations_test.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 4b5ce6313a..7c4bffaddd 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -134,9 +134,26 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase members.first.organization_member_details end - # TODO: has_many through + # has_many through # Source: has_many # Through: has_one through + def test_has_many_through_has_one_through_with_has_many_source_reflection + assert_equal [member_details(:groucho), member_details(:some_other_guy)], + members(:groucho).organization_member_details_2 + + members = Member.joins(:organization_member_details_2). + where('member_details.id' => member_details(:groucho).id) + assert_equal [members(:groucho), members(:some_other_guy)], members + + members = Member.joins(:organization_member_details_2). + where('member_details.id' => 9) + assert members.empty? + + # TODO: Make this work + # members = Member.includes(:organization_member_details_2) + # assert_equal [member_details(:groucho), member_details(:some_other_guy)], + # members.first.organization_member_details_2 + end # TODO: has_many through # Source: has_and_belongs_to_many -- cgit v1.2.3 From c37a5e7acde436b359043a67b7daace8be6f08c6 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 12 Oct 2010 18:16:31 +0100 Subject: Add a commented, failing test for using a habtm in a has many through association. I want to refactor how aliasing works first. --- .../associations/has_and_belongs_to_many_associations_test.rb | 8 ++++---- .../associations/nested_has_many_through_associations_test.rb | 9 +++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 7e070e1746..e67cbcc1a8 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -713,13 +713,13 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase def test_find_grouped all_posts_from_category1 = Post.find(:all, :conditions => "category_id = 1", :joins => :categories) grouped_posts_of_category1 = Post.find(:all, :conditions => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories) - assert_equal 4, all_posts_from_category1.size - assert_equal 1, grouped_posts_of_category1.size + assert_equal 5, all_posts_from_category1.size + assert_equal 2, grouped_posts_of_category1.size end def test_find_scoped_grouped - assert_equal 4, categories(:general).posts_grouped_by_title.size - assert_equal 1, categories(:technology).posts_grouped_by_title.size + assert_equal 5, categories(:general).posts_grouped_by_title.size + assert_equal 2, categories(:technology).posts_grouped_by_title.size end def test_find_scoped_grouped_having diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 7c4bffaddd..835a573978 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -24,6 +24,7 @@ require 'models/member_type' require 'models/sponsor' require 'models/club' require 'models/organization' +require 'models/category' # NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which # are just one level deep. But it's all the same thing really, as the "nested" code is being @@ -33,7 +34,7 @@ require 'models/organization' class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, - :member_types, :sponsors, :clubs, :organizations + :member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts # Through associations can either use the has_many or has_one macros. # @@ -155,9 +156,13 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # members.first.organization_member_details_2 end - # TODO: has_many through + # has_many through # Source: has_and_belongs_to_many # Through: has_many + # TODO: Enable and implement this, and finish off the test + # def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection + # assert_equal [categories(:general), categories(:technology)], authors(:bob).post_categories + # end # TODO: has_many through # Source: has_many -- cgit v1.2.3 From 781ad0f8fee209bcf10c5e52daae246477d49ea7 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Wed, 13 Oct 2010 01:29:09 +0100 Subject: First bit of support for habtm in through assocs - test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection now passes --- .../has_and_belongs_to_many_associations_test.rb | 2 +- .../nested_has_many_through_associations_test.rb | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index e67cbcc1a8..c6777d0cb3 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -719,7 +719,7 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase def test_find_scoped_grouped assert_equal 5, categories(:general).posts_grouped_by_title.size - assert_equal 2, categories(:technology).posts_grouped_by_title.size + assert_equal 1, categories(:technology).posts_grouped_by_title.size end def test_find_scoped_grouped_having diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 835a573978..964112b006 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -159,10 +159,15 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # has_many through # Source: has_and_belongs_to_many # Through: has_many - # TODO: Enable and implement this, and finish off the test - # def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection - # assert_equal [categories(:general), categories(:technology)], authors(:bob).post_categories - # end + def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection + assert_equal [categories(:general), categories(:cooking)], authors(:bob).post_categories + + authors = Author.joins(:post_categories).where('categories.id' => categories(:cooking).id) + assert_equal [authors(:bob)], authors + + authors = Author.includes(:post_categories) + assert_equal [categories(:general), categories(:cooking)], authors[2].post_categories + end # TODO: has_many through # Source: has_many -- cgit v1.2.3 From 212fdd8ba9624f61421a7a950283537a3d39ac18 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Wed, 13 Oct 2010 18:36:51 +0100 Subject: Add test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection and make it work --- .../nested_has_many_through_associations_test.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 964112b006..4e7e766b14 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -169,9 +169,19 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [categories(:general), categories(:cooking)], authors[2].post_categories end - # TODO: has_many through + # has_many through # Source: has_many # Through: has_and_belongs_to_many + def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection + assert_equal [comments(:greetings), comments(:more_greetings)], categories(:technology).post_comments + + categories = Category.joins(:post_comments).where('comments.id' => comments(:more_greetings).id) + assert_equal [categories(:general), categories(:technology)], categories + + # TODO: Make this work + # categories = Category.includes(:post_comments) + # assert_equal [comments(:greetings), comments(:more_greetings)], categories[1].post_comments + end # TODO: has_many through # Source: belongs_to -- cgit v1.2.3 From bc821a56114ae6f6d0b595475ad9e71f01f46f35 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 14 Oct 2010 12:59:16 +0100 Subject: Added test_has_many_through_has_many_with_has_many_through_habtm_source_reflection and make it pass --- activerecord/test/cases/associations/join_model_test.rb | 2 +- .../nested_has_many_through_associations_test.rb | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index 4b7a8b494d..385505b109 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -304,7 +304,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase end def test_has_many_going_through_join_model_with_custom_foreign_key - assert_equal [], posts(:thinking).authors + assert_equal [authors(:bob)], posts(:thinking).authors assert_equal [authors(:mary)], posts(:authorless).authors end diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 4e7e766b14..26c31ef761 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -25,6 +25,7 @@ require 'models/sponsor' require 'models/club' require 'models/organization' require 'models/category' +require 'models/categorization' # NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which # are just one level deep. But it's all the same thing really, as the "nested" code is being @@ -34,7 +35,8 @@ require 'models/category' class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, - :member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts + :member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts, + :categorizations # Through associations can either use the has_many or has_one macros. # @@ -183,6 +185,19 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # assert_equal [comments(:greetings), comments(:more_greetings)], categories[1].post_comments end + # has_many through + # Source: has_many through a habtm + # Through: has_many through + def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection + assert_equal [comments(:greetings), comments(:more_greetings)], authors(:bob).category_post_comments + + authors = Author.joins(:category_post_comments).where('comments.id' => comments(:does_it_hurt).id) + assert_equal [authors(:david), authors(:mary)], authors + + comments = Author.joins(:category_post_comments) + assert_equal [comments(:greetings), comments(:more_greetings)], comments[2].category_post_comments + end + # TODO: has_many through # Source: belongs_to # Through: has_many through -- cgit v1.2.3 From 7963c30ebaeb511f7ddacc99ae2c7a530059ae6b Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 14 Oct 2010 13:07:28 +0100 Subject: Add test_has_many_through_has_many_through_with_belongs_to_source_reflection (which already works) --- .../nested_has_many_through_associations_test.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 26c31ef761..7e1fc60cb9 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -198,9 +198,20 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [comments(:greetings), comments(:more_greetings)], comments[2].category_post_comments end - # TODO: has_many through + # has_many through # Source: belongs_to # Through: has_many through + def test_has_many_through_has_many_through_with_belongs_to_source_reflection + author = authors(:david) + assert_equal [tags(:general), tags(:general)], author.tagging_tags + + authors = Author.joins(:tagging_tags).where('tags.id' => tags(:general).id) + assert_equal [authors(:david)], authors.uniq + + # TODO: Make this work + # authors = Author.includes(:tagging_tags) + # assert_equal [tags(:general), tags(:general)], authors.first.tagging_tags + end # TODO: has_many through # Source: has_many through -- cgit v1.2.3 From 25acd19da5f75a425218740fbb187b18bbb060ce Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 14 Oct 2010 13:16:47 +0100 Subject: Add test_has_many_through_belongs_to_with_has_many_through_source_reflection (which already passes) --- .../nested_has_many_through_associations_test.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 7e1fc60cb9..6212eed0eb 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -213,9 +213,20 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # assert_equal [tags(:general), tags(:general)], authors.first.tagging_tags end - # TODO: has_many through + # has_many through # Source: has_many through # Through: belongs_to + def test_has_many_through_belongs_to_with_has_many_through_source_reflection + assert_equal [taggings(:welcome_general), taggings(:thinking_general)], + categorizations(:david_welcome_general).post_taggings + + categorizations = Categorization.joins(:post_taggings).where('taggings.id' => taggings(:welcome_general).id) + assert_equal [categorizations(:david_welcome_general)], categorizations + + categorizations = Categorization.includes(:post_taggings) + assert_equal [taggings(:welcome_general), taggings(:thinking_general)], + categorizations.first.post_taggings + end # has_one through # Source: has_one through -- cgit v1.2.3 From 002985fb66ae63f157db84f83520c3c256c04f77 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 14 Oct 2010 13:44:32 +0100 Subject: Add test_has_one_through_has_one_through_with_belongs_to_source_reflection --- .../nested_has_many_through_associations_test.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 6212eed0eb..0bd19c10e0 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -26,6 +26,7 @@ require 'models/club' require 'models/organization' require 'models/category' require 'models/categorization' +require 'models/membership' # NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which # are just one level deep. But it's all the same thing really, as the "nested" code is being @@ -36,7 +37,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, :member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts, - :categorizations + :categorizations, :memberships # Through associations can either use the has_many or has_one macros. # @@ -241,9 +242,19 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal member_types(:founding), members.first.nested_member_type end - # TODO: has_one through + # has_one through # Source: belongs_to # Through: has_one through + def test_has_one_through_has_one_through_with_belongs_to_source_reflection + assert_equal categories(:general), members(:groucho).club_category + + members = Member.joins(:club_category).where('categories.id' => categories(:technology).id) + assert_equal [members(:blarpy_winkup)], members + + # TODO: Make this work + # members = Member.includes(:club_category) + # assert_equal categories(:general), members.first.club_category + end def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection author = authors(:david) -- cgit v1.2.3 From 11508db1be0016bb1a9893c7b2062845233f78e0 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 14 Oct 2010 13:52:38 +0100 Subject: Remove unnecessary requires from nested_has_many_through_associations_test.rb --- .../cases/associations/nested_has_many_through_associations_test.rb | 6 ------ 1 file changed, 6 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 0bd19c10e0..eea1c4e54c 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -8,12 +8,6 @@ require 'models/reader' require 'models/comment' require 'models/tag' require 'models/tagging' -require 'models/owner' -require 'models/pet' -require 'models/toy' -require 'models/contract' -require 'models/company' -require 'models/developer' require 'models/subscriber' require 'models/book' require 'models/subscription' -- cgit v1.2.3 From 06c64eb60611bdeeb55e35a4819ba65d74dbadc3 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 15 Oct 2010 15:46:19 +0100 Subject: Support preloading nested through associations (using the default multi-query strategy) --- .../nested_has_many_through_associations_test.rb | 201 ++++++++++++++------- 1 file changed, 140 insertions(+), 61 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index eea1c4e54c..32b03bf076 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -54,70 +54,98 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase # Source: has_many through # Through: has_many def test_has_many_through_has_many_with_has_many_through_source_reflection - author = authors(:david) - assert_equal [tags(:general), tags(:general)], author.tags + general = tags(:general) + + assert_equal [general, general], authors(:david).tags # Only David has a Post tagged with General authors = Author.joins(:tags).where('tags.id' => tags(:general).id) assert_equal [authors(:david)], authors.uniq - authors = Author.includes(:tags) - assert_equal [tags(:general), tags(:general)], authors.first.tags - # This ensures that the polymorphism of taggings is being observed correctly authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel') assert authors.empty? + + assert_queries(5) do + authors = Author.includes(:tags).to_a + end + + assert_no_queries do + assert_equal [general, general], authors.first.tags + end end # has_many through # Source: has_many # Through: has_many through def test_has_many_through_has_many_through_with_has_many_source_reflection + luke, david = subscribers(:first), subscribers(:second) + author = authors(:david) - assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], author.subscribers + assert_equal [luke, david, david], author.subscribers # All authors with subscribers where one of the subscribers' nick is 'alterself' authors = Author.joins(:subscribers).where('subscribers.nick' => 'alterself') assert_equal [authors(:david)], authors - # TODO: Make this work - # authors = Author.includes(:subscribers) - # assert_equal [subscribers(:first), subscribers(:second), subscribers(:second)], authors.first.subscribers + assert_queries(4) do + authors = Author.includes(:subscribers).to_a + end + + assert_no_queries do + assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick) + end + + # TODO: Add eager loading test using LEFT OUTER JOIN end # has_many through # Source: has_one through # Through: has_one def test_has_many_through_has_one_with_has_one_through_source_reflection - assert_equal [member_types(:founding)], members(:groucho).nested_member_types + founding = member_types(:founding) + + assert_equal [founding], members(:groucho).nested_member_types - members = Member.joins(:nested_member_types).where('member_types.id' => member_types(:founding).id) + members = Member.joins(:nested_member_types).where('member_types.id' => founding.id) assert_equal [members(:groucho)], members - members = Member.includes(:nested_member_types) - assert_equal [member_types(:founding)], members.first.nested_member_types + assert_queries(4) do + members = Member.includes(:nested_member_types).to_a + end + + assert_no_queries do + assert_equal [founding], members.first.nested_member_types + end end # has_many through # Source: has_one # Through: has_one through def test_has_many_through_has_one_through_with_has_one_source_reflection - assert_equal [sponsors(:moustache_club_sponsor_for_groucho)], members(:groucho).nested_sponsors + mustache = sponsors(:moustache_club_sponsor_for_groucho) - members = Member.joins(:nested_sponsors).where('sponsors.id' => sponsors(:moustache_club_sponsor_for_groucho).id) + assert_equal [mustache], members(:groucho).nested_sponsors + + members = Member.joins(:nested_sponsors).where('sponsors.id' => mustache.id) assert_equal [members(:groucho)], members - # TODO: Make this work - # members = Member.includes(:nested_sponsors) - # assert_equal [sponsors(:moustache_club_sponsor_for_groucho)], members.first.nested_sponsors + assert_queries(4) do + members = Member.includes(:nested_sponsors).to_a + end + + assert_no_queries do + assert_equal [mustache], members.first.nested_sponsors + end end # has_many through # Source: has_many through # Through: has_one def test_has_many_through_has_one_with_has_many_through_source_reflection - assert_equal [member_details(:groucho), member_details(:some_other_guy)], - members(:groucho).organization_member_details + groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) + + assert_equal [groucho_details, other_details], members(:groucho).organization_member_details members = Member.joins(:organization_member_details). where('member_details.id' => member_details(:groucho).id) @@ -127,127 +155,178 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase where('member_details.id' => 9) assert members.empty? - members = Member.includes(:organization_member_details) - assert_equal [member_details(:groucho), member_details(:some_other_guy)], - members.first.organization_member_details + assert_queries(4) do + members = Member.includes(:organization_member_details).to_a + end + + assert_no_queries do + assert_equal [groucho_details, other_details], members.first.organization_member_details + end end # has_many through # Source: has_many # Through: has_one through def test_has_many_through_has_one_through_with_has_many_source_reflection - assert_equal [member_details(:groucho), member_details(:some_other_guy)], - members(:groucho).organization_member_details_2 + groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) + + assert_equal [groucho_details, other_details], members(:groucho).organization_member_details_2 members = Member.joins(:organization_member_details_2). - where('member_details.id' => member_details(:groucho).id) + where('member_details.id' => groucho_details.id) assert_equal [members(:groucho), members(:some_other_guy)], members members = Member.joins(:organization_member_details_2). where('member_details.id' => 9) assert members.empty? - # TODO: Make this work - # members = Member.includes(:organization_member_details_2) - # assert_equal [member_details(:groucho), member_details(:some_other_guy)], - # members.first.organization_member_details_2 + assert_queries(4) do + members = Member.includes(:organization_member_details_2).to_a + end + + assert_no_queries do + assert_equal [groucho_details, other_details], members.first.organization_member_details_2 + end end # has_many through # Source: has_and_belongs_to_many # Through: has_many def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection - assert_equal [categories(:general), categories(:cooking)], authors(:bob).post_categories + general, cooking = categories(:general), categories(:cooking) + + assert_equal [general, cooking], authors(:bob).post_categories - authors = Author.joins(:post_categories).where('categories.id' => categories(:cooking).id) + authors = Author.joins(:post_categories).where('categories.id' => cooking.id) assert_equal [authors(:bob)], authors - authors = Author.includes(:post_categories) - assert_equal [categories(:general), categories(:cooking)], authors[2].post_categories + assert_queries(3) do + authors = Author.includes(:post_categories).to_a + end + + assert_no_queries do + assert_equal [general, cooking], authors[2].post_categories + end end # has_many through # Source: has_many # Through: has_and_belongs_to_many def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection - assert_equal [comments(:greetings), comments(:more_greetings)], categories(:technology).post_comments + greetings, more = comments(:greetings), comments(:more_greetings) + + assert_equal [greetings, more], categories(:technology).post_comments - categories = Category.joins(:post_comments).where('comments.id' => comments(:more_greetings).id) + categories = Category.joins(:post_comments).where('comments.id' => more.id) assert_equal [categories(:general), categories(:technology)], categories - # TODO: Make this work - # categories = Category.includes(:post_comments) - # assert_equal [comments(:greetings), comments(:more_greetings)], categories[1].post_comments + assert_queries(3) do + categories = Category.includes(:post_comments).to_a + end + + assert_no_queries do + assert_equal [greetings, more], categories[1].post_comments + end end # has_many through # Source: has_many through a habtm # Through: has_many through def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection - assert_equal [comments(:greetings), comments(:more_greetings)], authors(:bob).category_post_comments + greetings, more = comments(:greetings), comments(:more_greetings) + + assert_equal [greetings, more], authors(:bob).category_post_comments authors = Author.joins(:category_post_comments).where('comments.id' => comments(:does_it_hurt).id) assert_equal [authors(:david), authors(:mary)], authors - comments = Author.joins(:category_post_comments) - assert_equal [comments(:greetings), comments(:more_greetings)], comments[2].category_post_comments + assert_queries(5) do + authors = Author.includes(:category_post_comments).to_a + end + + assert_no_queries do + assert_equal [greetings, more], authors[2].category_post_comments + end end # has_many through # Source: belongs_to # Through: has_many through def test_has_many_through_has_many_through_with_belongs_to_source_reflection - author = authors(:david) - assert_equal [tags(:general), tags(:general)], author.tagging_tags + general = tags(:general) + + assert_equal [general, general], authors(:david).tagging_tags authors = Author.joins(:tagging_tags).where('tags.id' => tags(:general).id) assert_equal [authors(:david)], authors.uniq - # TODO: Make this work - # authors = Author.includes(:tagging_tags) - # assert_equal [tags(:general), tags(:general)], authors.first.tagging_tags + assert_queries(5) do + authors = Author.includes(:tagging_tags).to_a + end + + assert_no_queries do + assert_equal [general, general], authors.first.tagging_tags + end end # has_many through # Source: has_many through # Through: belongs_to def test_has_many_through_belongs_to_with_has_many_through_source_reflection - assert_equal [taggings(:welcome_general), taggings(:thinking_general)], - categorizations(:david_welcome_general).post_taggings + welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general) + + assert_equal [welcome_general, thinking_general], categorizations(:david_welcome_general).post_taggings - categorizations = Categorization.joins(:post_taggings).where('taggings.id' => taggings(:welcome_general).id) + categorizations = Categorization.joins(:post_taggings).where('taggings.id' => welcome_general.id) assert_equal [categorizations(:david_welcome_general)], categorizations - categorizations = Categorization.includes(:post_taggings) - assert_equal [taggings(:welcome_general), taggings(:thinking_general)], - categorizations.first.post_taggings + assert_queries(4) do + categorizations = Categorization.includes(:post_taggings).to_a + end + + assert_no_queries do + assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings + end end # has_one through # Source: has_one through # Through: has_one def test_has_one_through_has_one_with_has_one_through_source_reflection - assert_equal member_types(:founding), members(:groucho).nested_member_type + founding = member_types(:founding) + + assert_equal founding, members(:groucho).nested_member_type - members = Member.joins(:nested_member_type).where('member_types.id' => member_types(:founding).id) + members = Member.joins(:nested_member_type).where('member_types.id' => founding.id) assert_equal [members(:groucho)], members - members = Member.includes(:nested_member_type) - assert_equal member_types(:founding), members.first.nested_member_type + assert_queries(4) do + members = Member.includes(:nested_member_type).to_a + end + + assert_no_queries do + assert_equal founding, members.first.nested_member_type + end end # has_one through # Source: belongs_to # Through: has_one through def test_has_one_through_has_one_through_with_belongs_to_source_reflection - assert_equal categories(:general), members(:groucho).club_category + general = categories(:general) + + assert_equal general, members(:groucho).club_category members = Member.joins(:club_category).where('categories.id' => categories(:technology).id) assert_equal [members(:blarpy_winkup)], members - # TODO: Make this work - # members = Member.includes(:club_category) - # assert_equal categories(:general), members.first.club_category + assert_queries(4) do + members = Member.includes(:club_category).to_a + end + + assert_no_queries do + assert_equal general, members.first.club_category + end end def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection -- cgit v1.2.3 From 1e2525bfe0248d873d6d6026f45102853a1c95cd Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 15 Oct 2010 16:21:42 +0100 Subject: Add assertions for nested through associations loaded by includes with conditions (uses the single-query strategy). Currently one failure to fix. --- .../nested_has_many_through_associations_test.rb | 156 ++++++++++----------- 1 file changed, 75 insertions(+), 81 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 32b03bf076..4d5152ed5d 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -58,18 +58,16 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [general, general], authors(:david).tags - # Only David has a Post tagged with General - authors = Author.joins(:tags).where('tags.id' => tags(:general).id) - assert_equal [authors(:david)], authors.uniq + assert_includes_and_joins_equal( + Author.where('tags.id' => tags(:general).id), + [authors(:david)], :tags + ) # This ensures that the polymorphism of taggings is being observed correctly authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel') assert authors.empty? - assert_queries(5) do - authors = Author.includes(:tags).to_a - end - + authors = assert_queries(5) { Author.includes(:tags).to_a } assert_no_queries do assert_equal [general, general], authors.first.tags end @@ -85,13 +83,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [luke, david, david], author.subscribers # All authors with subscribers where one of the subscribers' nick is 'alterself' - authors = Author.joins(:subscribers).where('subscribers.nick' => 'alterself') - assert_equal [authors(:david)], authors - - assert_queries(4) do - authors = Author.includes(:subscribers).to_a - end + assert_includes_and_joins_equal( + Author.where('subscribers.nick' => 'alterself'), + [authors(:david)], :subscribers + ) + authors = assert_queries(4) { Author.includes(:subscribers).to_a } assert_no_queries do assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick) end @@ -107,13 +104,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [founding], members(:groucho).nested_member_types - members = Member.joins(:nested_member_types).where('member_types.id' => founding.id) - assert_equal [members(:groucho)], members - - assert_queries(4) do - members = Member.includes(:nested_member_types).to_a - end + assert_includes_and_joins_equal( + Member.where('member_types.id' => founding.id), + [members(:groucho)], :nested_member_types + ) + members = assert_queries(4) { Member.includes(:nested_member_types).to_a } assert_no_queries do assert_equal [founding], members.first.nested_member_types end @@ -127,13 +123,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [mustache], members(:groucho).nested_sponsors - members = Member.joins(:nested_sponsors).where('sponsors.id' => mustache.id) - assert_equal [members(:groucho)], members - - assert_queries(4) do - members = Member.includes(:nested_sponsors).to_a - end + assert_includes_and_joins_equal( + Member.where('sponsors.id' => mustache.id), + [members(:groucho)], :nested_sponsors + ) + members = assert_queries(4) { Member.includes(:nested_sponsors).to_a } assert_no_queries do assert_equal [mustache], members.first.nested_sponsors end @@ -147,18 +142,16 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [groucho_details, other_details], members(:groucho).organization_member_details - members = Member.joins(:organization_member_details). - where('member_details.id' => member_details(:groucho).id) - assert_equal [members(:groucho), members(:some_other_guy)], members + assert_includes_and_joins_equal( + Member.where('member_details.id' => member_details(:groucho).id), + [members(:groucho), members(:some_other_guy)], :organization_member_details + ) members = Member.joins(:organization_member_details). where('member_details.id' => 9) assert members.empty? - assert_queries(4) do - members = Member.includes(:organization_member_details).to_a - end - + members = assert_queries(4) { Member.includes(:organization_member_details).to_a } assert_no_queries do assert_equal [groucho_details, other_details], members.first.organization_member_details end @@ -172,18 +165,16 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [groucho_details, other_details], members(:groucho).organization_member_details_2 - members = Member.joins(:organization_member_details_2). - where('member_details.id' => groucho_details.id) - assert_equal [members(:groucho), members(:some_other_guy)], members + assert_includes_and_joins_equal( + Member.where('member_details.id' => groucho_details.id), + [members(:groucho), members(:some_other_guy)], :organization_member_details_2 + ) members = Member.joins(:organization_member_details_2). where('member_details.id' => 9) assert members.empty? - assert_queries(4) do - members = Member.includes(:organization_member_details_2).to_a - end - + members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a } assert_no_queries do assert_equal [groucho_details, other_details], members.first.organization_member_details_2 end @@ -197,13 +188,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [general, cooking], authors(:bob).post_categories - authors = Author.joins(:post_categories).where('categories.id' => cooking.id) - assert_equal [authors(:bob)], authors - - assert_queries(3) do - authors = Author.includes(:post_categories).to_a - end + assert_includes_and_joins_equal( + Author.where('categories.id' => cooking.id), + [authors(:bob)], :post_categories + ) + authors = assert_queries(3) { Author.includes(:post_categories).to_a } assert_no_queries do assert_equal [general, cooking], authors[2].post_categories end @@ -217,13 +207,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [greetings, more], categories(:technology).post_comments - categories = Category.joins(:post_comments).where('comments.id' => more.id) - assert_equal [categories(:general), categories(:technology)], categories - - assert_queries(3) do - categories = Category.includes(:post_comments).to_a - end + assert_includes_and_joins_equal( + Category.where('comments.id' => more.id), + [categories(:general), categories(:technology)], :post_comments + ) + categories = assert_queries(3) { Category.includes(:post_comments).to_a } assert_no_queries do assert_equal [greetings, more], categories[1].post_comments end @@ -237,13 +226,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [greetings, more], authors(:bob).category_post_comments - authors = Author.joins(:category_post_comments).where('comments.id' => comments(:does_it_hurt).id) - assert_equal [authors(:david), authors(:mary)], authors - - assert_queries(5) do - authors = Author.includes(:category_post_comments).to_a - end + assert_includes_and_joins_equal( + Author.where('comments.id' => comments(:does_it_hurt).id), + [authors(:david), authors(:mary)], :category_post_comments + ) + authors = assert_queries(5) { Author.includes(:category_post_comments).to_a } assert_no_queries do assert_equal [greetings, more], authors[2].category_post_comments end @@ -257,13 +245,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [general, general], authors(:david).tagging_tags - authors = Author.joins(:tagging_tags).where('tags.id' => tags(:general).id) - assert_equal [authors(:david)], authors.uniq - - assert_queries(5) do - authors = Author.includes(:tagging_tags).to_a - end + assert_includes_and_joins_equal( + Author.where('tags.id' => tags(:general).id), + [authors(:david)], :tagging_tags + ) + authors = assert_queries(5) { Author.includes(:tagging_tags).to_a } assert_no_queries do assert_equal [general, general], authors.first.tagging_tags end @@ -277,13 +264,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal [welcome_general, thinking_general], categorizations(:david_welcome_general).post_taggings - categorizations = Categorization.joins(:post_taggings).where('taggings.id' => welcome_general.id) - assert_equal [categorizations(:david_welcome_general)], categorizations - - assert_queries(4) do - categorizations = Categorization.includes(:post_taggings).to_a - end + assert_includes_and_joins_equal( + Categorization.where('taggings.id' => welcome_general.id), + [categorizations(:david_welcome_general)], :post_taggings + ) + categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a } assert_no_queries do assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings end @@ -297,13 +283,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal founding, members(:groucho).nested_member_type - members = Member.joins(:nested_member_type).where('member_types.id' => founding.id) - assert_equal [members(:groucho)], members - - assert_queries(4) do - members = Member.includes(:nested_member_type).to_a - end + assert_includes_and_joins_equal( + Member.where('member_types.id' => founding.id), + [members(:groucho)], :nested_member_type + ) + members = assert_queries(4) { Member.includes(:nested_member_type).to_a } assert_no_queries do assert_equal founding, members.first.nested_member_type end @@ -317,13 +302,12 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal general, members(:groucho).club_category - members = Member.joins(:club_category).where('categories.id' => categories(:technology).id) - assert_equal [members(:blarpy_winkup)], members - - assert_queries(4) do - members = Member.includes(:club_category).to_a - end + assert_includes_and_joins_equal( + Member.where('categories.id' => categories(:technology).id), + [members(:blarpy_winkup)], :club_category + ) + members = assert_queries(4) { Member.includes(:club_category).to_a } assert_no_queries do assert_equal general, members.first.club_category end @@ -379,4 +363,14 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert !scope.where("comments.type" => "SpecialComment").empty? assert !scope.where("comments.type" => "SubSpecialComment").empty? end + + private + + def assert_includes_and_joins_equal(query, expected, association) + actual = assert_queries(1) { query.joins(association).to_a.uniq } + assert_equal expected, actual + + actual = assert_queries(1) { query.includes(association).to_a.uniq } + assert_equal expected, actual + end end -- cgit v1.2.3 From edc176d33be9499f4c096779c5b4711b5daf0c06 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 15 Oct 2010 17:46:09 +0100 Subject: Make sure nested through associations are read only --- .../nested_has_many_through_associations_test.rb | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 4d5152ed5d..03ec4281d8 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -363,6 +363,48 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert !scope.where("comments.type" => "SpecialComment").empty? assert !scope.where("comments.type" => "SubSpecialComment").empty? end + + def test_nested_has_many_through_writers_should_raise_error + david = authors(:david) + subscriber = subscribers(:first) + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers = [subscriber] + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscriber_ids = [subscriber.id] + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers << subscriber + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers.delete(subscriber) + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers.clear + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers.build + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers.create + end + end + + def test_nested_has_one_through_writers_should_raise_error + groucho = members(:groucho) + founding = member_types(:founding) + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + groucho.nested_member_type = founding + end + end private -- cgit v1.2.3 From 9ec07348749675110843c44f680da79223218db2 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 19 Oct 2010 00:27:40 +0100 Subject: Properly support conditions on any of the reflections involved in a nested through association --- .../associations/cascaded_eager_loading_test.rb | 6 ++-- activerecord/test/cases/associations/eager_test.rb | 4 +-- .../nested_has_many_through_associations_test.rb | 40 ++++++++++++++++++++-- 3 files changed, 42 insertions(+), 8 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index 0e9c8a2639..5b24d49a7d 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -15,7 +15,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id") assert_equal 3, authors.size assert_equal 5, authors[0].posts.size - assert_equal 2, authors[1].posts.size + assert_equal 3, authors[1].posts.size assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} end @@ -23,7 +23,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase authors = Author.find(:all, :include=>[{:posts=>:comments}, :categorizations], :order=>"authors.id") assert_equal 3, authors.size assert_equal 5, authors[0].posts.size - assert_equal 2, authors[1].posts.size + assert_equal 3, authors[1].posts.size assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} assert_equal 1, authors[0].categorizations.size assert_equal 2, authors[1].categorizations.size @@ -56,7 +56,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase authors = Author.find(:all, :include=>{:posts=>[:comments, :categorizations]}, :order=>"authors.id") assert_equal 3, authors.size assert_equal 5, authors[0].posts.size - assert_equal 2, authors[1].posts.size + assert_equal 3, authors[1].posts.size assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 2ff0714e9f..6b910ae2a0 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -53,8 +53,8 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_with_ordering list = Post.find(:all, :include => :comments, :order => "posts.id DESC") - [:misc_by_mary, :misc_by_bob, :eager_other, :sti_habtm, :sti_post_and_comments, - :sti_comments, :authorless, :thinking, :welcome + [:other_by_mary, :other_by_bob, :misc_by_mary, :misc_by_bob, :eager_other, + :sti_habtm, :sti_post_and_comments, :sti_comments, :authorless, :thinking, :welcome ].each_with_index do |post, index| assert_equal posts(post), list[index] end diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 03ec4281d8..c39ec5d139 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -92,8 +92,6 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert_no_queries do assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick) end - - # TODO: Add eager loading test using LEFT OUTER JOIN end # has_many through @@ -325,7 +323,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_nested_has_many_through_with_a_table_referenced_multiple_times author = authors(:bob) - assert_equal [posts(:misc_by_bob), posts(:misc_by_mary)], author.similar_posts.sort_by(&:id) + assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)], author.similar_posts.sort_by(&:id) # Mary and Bob both have posts in misc, but they are the only ones. authors = Author.joins(:similar_posts).where('posts.id' => posts(:misc_by_bob).id) @@ -406,6 +404,42 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase end end + def test_nested_has_many_through_with_conditions_on_through_associations + blue, bob = tags(:blue), authors(:bob) + + assert_equal [blue], bob.misc_post_first_blue_tags + + # Pointless condition to force single-query loading + assert_includes_and_joins_equal( + Author.where('tags.id = tags.id'), + [bob], :misc_post_first_blue_tags + ) + + assert Author.where('tags.id' => 100).joins(:misc_post_first_blue_tags).empty? + + authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a } + assert_no_queries do + assert_equal [blue], authors[2].misc_post_first_blue_tags + end + end + + def test_nested_has_many_through_with_conditions_on_source_associations + blue, bob = tags(:blue), authors(:bob) + + assert_equal [blue], bob.misc_post_first_blue_tags_2 + + # Pointless condition to force single-query loading + assert_includes_and_joins_equal( + Author.where('tags.id = tags.id'), + [bob], :misc_post_first_blue_tags_2 + ) + + authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a } + assert_no_queries do + assert_equal [blue], authors[2].misc_post_first_blue_tags_2 + end + end + private def assert_includes_and_joins_equal(query, expected, association) -- cgit v1.2.3 From 596cc3b2329a9cc4a30c95c157ce36b2d08975df Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 19 Oct 2010 12:47:19 +0100 Subject: Respect the :primary_key option on the through_reflection of (non-nested) through associations --- .../has_many_through_associations_test.rb | 19 ++++++++++++++++++- .../has_one_through_associations_test.rb | 20 +++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 4b9f49f1ec..5a2e6b26aa 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -17,11 +17,14 @@ require 'models/developer' require 'models/subscriber' require 'models/book' require 'models/subscription' +require 'models/essay' +require 'models/category' class HasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys, :jobs, :references, :companies, - :subscribers, :books, :subscriptions, :developers + :subscribers, :books, :subscriptions, :developers, + :essays, :categories # Dummies to force column loads so query counts are clean. def setup @@ -449,4 +452,18 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase comment = post.comments.build assert author.comments.include?(comment) end + + def test_has_many_through_polymorphic_with_primary_key_option_on_through_reflection + assert_equal [categories(:general)], authors(:david).essay_categories + + authors = Author.joins(:essay_categories).where('categories.id' => categories(:general).id) + assert_equal authors(:david), authors.first + end + + def test_has_many_through_with_primary_key_option_on_through_reflection + assert_equal [categories(:general)], authors(:david).essay_categories_2 + + authors = Author.joins(:essay_categories_2).where('categories.id' => categories(:general).id) + assert_equal authors(:david), authors.first + end end diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index 5d153147f5..8805968869 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -9,9 +9,13 @@ require 'models/member_detail' require 'models/minivan' require 'models/dashboard' require 'models/speedometer' +require 'models/category' +require 'models/author' +require 'models/essay' class HasOneThroughAssociationsTest < ActiveRecord::TestCase - fixtures :member_types, :members, :clubs, :memberships, :sponsors, :organizations, :minivans, :dashboards, :speedometers + fixtures :member_types, :members, :clubs, :memberships, :sponsors, :organizations, :minivans, + :dashboards, :speedometers, :categories, :authors, :essays def setup @member = members(:groucho) @@ -212,4 +216,18 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase minivan.dashboard end end + + def test_has_one_through_polymorphic_with_primary_key_option_on_through_reflection + assert_equal categories(:general), authors(:david).essay_category + + authors = Author.joins(:essay_category).where('categories.id' => categories(:general).id) + assert_equal authors(:david), authors.first + end + + def test_has_one_through_with_primary_key_option_on_through_reflection + assert_equal categories(:general), authors(:david).essay_category_2 + + authors = Author.joins(:essay_category_2).where('categories.id' => categories(:general).id) + assert_equal authors(:david), authors.first + end end -- cgit v1.2.3 From 01838636c6136d9a649ace71db61bb7990f9bd82 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 19 Oct 2010 14:14:06 +0100 Subject: Support for :primary_key option on the source reflection of a through association, where the source is a has_one or has_many --- .../cases/associations/has_many_through_associations_test.rb | 12 +++++++++--- .../cases/associations/has_one_through_associations_test.rb | 12 +++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 5a2e6b26aa..713c492f5e 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -19,12 +19,13 @@ require 'models/book' require 'models/subscription' require 'models/essay' require 'models/category' +require 'models/owner' class HasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys, :jobs, :references, :companies, :subscribers, :books, :subscriptions, :developers, - :essays, :categories + :essays, :categories, :owners # Dummies to force column loads so query counts are clean. def setup @@ -453,14 +454,19 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert author.comments.include?(comment) end - def test_has_many_through_polymorphic_with_primary_key_option_on_through_reflection + def test_has_many_through_polymorphic_with_primary_key_option assert_equal [categories(:general)], authors(:david).essay_categories authors = Author.joins(:essay_categories).where('categories.id' => categories(:general).id) assert_equal authors(:david), authors.first + + assert_equal [owners(:blackbeard)], authors(:david).essay_owners + + authors = Author.joins(:essay_owners).where("owners.name = 'blackbeard'") + assert_equal authors(:david), authors.first end - def test_has_many_through_with_primary_key_option_on_through_reflection + def test_has_many_through_with_primary_key_option assert_equal [categories(:general)], authors(:david).essay_categories_2 authors = Author.joins(:essay_categories_2).where('categories.id' => categories(:general).id) diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index 8805968869..39e14b4bfd 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -12,10 +12,11 @@ require 'models/speedometer' require 'models/category' require 'models/author' require 'models/essay' +require 'models/owner' class HasOneThroughAssociationsTest < ActiveRecord::TestCase fixtures :member_types, :members, :clubs, :memberships, :sponsors, :organizations, :minivans, - :dashboards, :speedometers, :categories, :authors, :essays + :dashboards, :speedometers, :categories, :authors, :essays, :owners def setup @member = members(:groucho) @@ -217,14 +218,19 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase end end - def test_has_one_through_polymorphic_with_primary_key_option_on_through_reflection + def test_has_one_through_polymorphic_with_primary_key_option assert_equal categories(:general), authors(:david).essay_category authors = Author.joins(:essay_category).where('categories.id' => categories(:general).id) assert_equal authors(:david), authors.first + + assert_equal owners(:blackbeard), authors(:david).essay_owner + + authors = Author.joins(:essay_owner).where("owners.name = 'blackbeard'") + assert_equal authors(:david), authors.first end - def test_has_one_through_with_primary_key_option_on_through_reflection + def test_has_one_through_with_primary_key_option assert_equal categories(:general), authors(:david).essay_category_2 authors = Author.joins(:essay_category_2).where('categories.id' => categories(:general).id) -- cgit v1.2.3 From 915ea5ea826d48107e4c1953c7a32cf26727d10e Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 19 Oct 2010 16:13:06 +0100 Subject: Support the :primary_key option on a through reflection in a nested through association --- .../nested_has_many_through_associations_test.rb | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index c39ec5d139..3a4601b032 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -21,6 +21,7 @@ require 'models/organization' require 'models/category' require 'models/categorization' require 'models/membership' +require 'models/essay' # NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which # are just one level deep. But it's all the same thing really, as the "nested" code is being @@ -31,7 +32,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, :member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts, - :categorizations, :memberships + :categorizations, :memberships, :essays # Through associations can either use the has_many or has_one macros. # @@ -440,6 +441,20 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase end end + def test_nested_has_many_through_with_foreign_key_option_on_the_source_reflection_through_reflection + assert_equal [categories(:general)], organizations(:nsa).author_essay_categories + + organizations = Organization.joins(:author_essay_categories). + where('categories.id' => categories(:general).id) + assert_equal [organizations(:nsa)], organizations + + assert_equal categories(:general), organizations(:nsa).author_owned_essay_category + + organizations = Organization.joins(:author_owned_essay_category). + where('categories.id' => categories(:general).id) + assert_equal [organizations(:nsa)], organizations + end + private def assert_includes_and_joins_equal(query, expected, association) -- cgit v1.2.3 From 7ee33b80a2048ec3801f02018b0ea81d2abe0011 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 19 Oct 2010 17:29:19 +0100 Subject: Remove various comments and code which were just being used during the development of nested through association support (OMFGZ, I might just have nearly finished this\! --- .../cases/associations/nested_has_many_through_associations_test.rb | 5 ----- 1 file changed, 5 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 3a4601b032..23fa1709ce 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -23,11 +23,6 @@ require 'models/categorization' require 'models/membership' require 'models/essay' -# NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which -# are just one level deep. But it's all the same thing really, as the "nested" code is being -# written in a generic way which applies to "non-nested" HMT associations too. So let's just shove -# all useful tests in here for now and then work out where they ought to live properly later. - class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, -- cgit v1.2.3 From d15de7d97f7080d8d3bc47bef89aa8a922f04c67 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 19 Oct 2010 19:25:44 +0100 Subject: Add explicit ordering to nested_has_many_through_associations_test.rb as this was causing failures under postgres --- .../nested_has_many_through_associations_test.rb | 69 ++++++++++++---------- 1 file changed, 37 insertions(+), 32 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb index 23fa1709ce..274ecdaba7 100644 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb @@ -76,7 +76,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase luke, david = subscribers(:first), subscribers(:second) author = authors(:david) - assert_equal [luke, david, david], author.subscribers + assert_equal [luke, david, david], author.subscribers.order('subscribers.nick') # All authors with subscribers where one of the subscribers' nick is 'alterself' assert_includes_and_joins_equal( @@ -134,10 +134,11 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_has_one_with_has_many_through_source_reflection groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) - assert_equal [groucho_details, other_details], members(:groucho).organization_member_details + assert_equal [groucho_details, other_details], + members(:groucho).organization_member_details.order('member_details.id') assert_includes_and_joins_equal( - Member.where('member_details.id' => member_details(:groucho).id), + Member.where('member_details.id' => member_details(:groucho).id).order('member_details.id'), [members(:groucho), members(:some_other_guy)], :organization_member_details ) @@ -145,9 +146,9 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase where('member_details.id' => 9) assert members.empty? - members = assert_queries(4) { Member.includes(:organization_member_details).to_a } + members = assert_queries(4) { Member.includes(:organization_member_details).to_a.sort_by(&:id) } assert_no_queries do - assert_equal [groucho_details, other_details], members.first.organization_member_details + assert_equal [groucho_details, other_details], members.first.organization_member_details.sort_by(&:id) end end @@ -157,10 +158,11 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_has_one_through_with_has_many_source_reflection groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) - assert_equal [groucho_details, other_details], members(:groucho).organization_member_details_2 + assert_equal [groucho_details, other_details], + members(:groucho).organization_member_details_2.order('member_details.id') assert_includes_and_joins_equal( - Member.where('member_details.id' => groucho_details.id), + Member.where('member_details.id' => groucho_details.id).order('member_details.id'), [members(:groucho), members(:some_other_guy)], :organization_member_details_2 ) @@ -168,9 +170,9 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase where('member_details.id' => 9) assert members.empty? - members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a } + members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a.sort_by(&:id) } assert_no_queries do - assert_equal [groucho_details, other_details], members.first.organization_member_details_2 + assert_equal [groucho_details, other_details], members.first.organization_member_details_2.sort_by(&:id) end end @@ -180,16 +182,16 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection general, cooking = categories(:general), categories(:cooking) - assert_equal [general, cooking], authors(:bob).post_categories + assert_equal [general, cooking], authors(:bob).post_categories.order('categories.id') assert_includes_and_joins_equal( Author.where('categories.id' => cooking.id), [authors(:bob)], :post_categories ) - authors = assert_queries(3) { Author.includes(:post_categories).to_a } + authors = assert_queries(3) { Author.includes(:post_categories).to_a.sort_by(&:id) } assert_no_queries do - assert_equal [general, cooking], authors[2].post_categories + assert_equal [general, cooking], authors[2].post_categories.sort_by(&:id) end end @@ -199,16 +201,16 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection greetings, more = comments(:greetings), comments(:more_greetings) - assert_equal [greetings, more], categories(:technology).post_comments + assert_equal [greetings, more], categories(:technology).post_comments.order('comments.id') assert_includes_and_joins_equal( - Category.where('comments.id' => more.id), + Category.where('comments.id' => more.id).order('comments.id'), [categories(:general), categories(:technology)], :post_comments ) - categories = assert_queries(3) { Category.includes(:post_comments).to_a } + categories = assert_queries(3) { Category.includes(:post_comments).to_a.sort_by(&:id) } assert_no_queries do - assert_equal [greetings, more], categories[1].post_comments + assert_equal [greetings, more], categories[1].post_comments.sort_by(&:id) end end @@ -218,16 +220,16 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection greetings, more = comments(:greetings), comments(:more_greetings) - assert_equal [greetings, more], authors(:bob).category_post_comments + assert_equal [greetings, more], authors(:bob).category_post_comments.order('comments.id') assert_includes_and_joins_equal( - Author.where('comments.id' => comments(:does_it_hurt).id), + Author.where('comments.id' => comments(:does_it_hurt).id).order('comments.id'), [authors(:david), authors(:mary)], :category_post_comments ) - authors = assert_queries(5) { Author.includes(:category_post_comments).to_a } + authors = assert_queries(5) { Author.includes(:category_post_comments).to_a.sort_by(&:id) } assert_no_queries do - assert_equal [greetings, more], authors[2].category_post_comments + assert_equal [greetings, more], authors[2].category_post_comments.sort_by(&:id) end end @@ -256,16 +258,17 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_belongs_to_with_has_many_through_source_reflection welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general) - assert_equal [welcome_general, thinking_general], categorizations(:david_welcome_general).post_taggings + assert_equal [welcome_general, thinking_general], + categorizations(:david_welcome_general).post_taggings.order('taggings.id') assert_includes_and_joins_equal( - Categorization.where('taggings.id' => welcome_general.id), + Categorization.where('taggings.id' => welcome_general.id).order('taggings.id'), [categorizations(:david_welcome_general)], :post_taggings ) - categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a } + categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a.sort_by(&:id) } assert_no_queries do - assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings + assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings.sort_by(&:id) end end @@ -282,7 +285,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase [members(:groucho)], :nested_member_type ) - members = assert_queries(4) { Member.includes(:nested_member_type).to_a } + members = assert_queries(4) { Member.includes(:nested_member_type).to_a.sort_by(&:id) } assert_no_queries do assert_equal founding, members.first.nested_member_type end @@ -301,7 +304,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase [members(:blarpy_winkup)], :club_category ) - members = assert_queries(4) { Member.includes(:club_category).to_a } + members = assert_queries(4) { Member.includes(:club_category).to_a.sort_by(&:id) } assert_no_queries do assert_equal general, members.first.club_category end @@ -314,12 +317,14 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection author = authors(:david) - assert_equal [subscribers(:first), subscribers(:second)], author.distinct_subscribers + assert_equal [subscribers(:first), subscribers(:second)], + author.distinct_subscribers.order('subscribers.nick') end def test_nested_has_many_through_with_a_table_referenced_multiple_times author = authors(:bob) - assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)], author.similar_posts.sort_by(&:id) + assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)], + author.similar_posts.sort_by(&:id) # Mary and Bob both have posts in misc, but they are the only ones. authors = Author.joins(:similar_posts).where('posts.id' => posts(:misc_by_bob).id) @@ -333,7 +338,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase end def test_has_many_through_with_foreign_key_option_on_through_reflection - assert_equal [posts(:welcome), posts(:authorless)], people(:david).agents_posts + assert_equal [posts(:welcome), posts(:authorless)], people(:david).agents_posts.order('posts.id') assert_equal [authors(:david)], references(:david_unicyclist).agents_posts_authors references = Reference.joins(:agents_posts_authors).where('authors.id' => authors(:david).id) @@ -341,7 +346,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase end def test_has_many_through_with_foreign_key_option_on_source_reflection - assert_equal [people(:michael), people(:susan)], jobs(:unicyclist).agents + assert_equal [people(:michael), people(:susan)], jobs(:unicyclist).agents.order('people.id') jobs = Job.joins(:agents) assert_equal [jobs(:unicyclist), jobs(:unicyclist)], jobs @@ -413,7 +418,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase assert Author.where('tags.id' => 100).joins(:misc_post_first_blue_tags).empty? - authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a } + authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a.sort_by(&:id) } assert_no_queries do assert_equal [blue], authors[2].misc_post_first_blue_tags end @@ -430,7 +435,7 @@ class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase [bob], :misc_post_first_blue_tags_2 ) - authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a } + authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) } assert_no_queries do assert_equal [blue], authors[2].misc_post_first_blue_tags_2 end -- cgit v1.2.3 From 8e53e058acea471eab7a1609dc150aa9fdbfa833 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Tue, 19 Oct 2010 21:41:00 +0100 Subject: Rename nested_has_many_through_associations_test.rb because it does not only concern has_many associations --- .../nested_has_many_through_associations_test.rb | 467 --------------------- .../nested_through_associations_test.rb | 467 +++++++++++++++++++++ 2 files changed, 467 insertions(+), 467 deletions(-) delete mode 100644 activerecord/test/cases/associations/nested_has_many_through_associations_test.rb create mode 100644 activerecord/test/cases/associations/nested_through_associations_test.rb (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb b/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb deleted file mode 100644 index 274ecdaba7..0000000000 --- a/activerecord/test/cases/associations/nested_has_many_through_associations_test.rb +++ /dev/null @@ -1,467 +0,0 @@ -require "cases/helper" -require 'models/author' -require 'models/post' -require 'models/person' -require 'models/reference' -require 'models/job' -require 'models/reader' -require 'models/comment' -require 'models/tag' -require 'models/tagging' -require 'models/subscriber' -require 'models/book' -require 'models/subscription' -require 'models/rating' -require 'models/member' -require 'models/member_detail' -require 'models/member_type' -require 'models/sponsor' -require 'models/club' -require 'models/organization' -require 'models/category' -require 'models/categorization' -require 'models/membership' -require 'models/essay' - -class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase - fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, - :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, - :member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts, - :categorizations, :memberships, :essays - - # Through associations can either use the has_many or has_one macros. - # - # has_many - # - Source reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many - # - Through reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many - # - # has_one - # - Source reflection can be has_one or belongs_to - # - Through reflection can be has_one or belongs_to - # - # Additionally, the source reflection and/or through reflection may be subject to - # polymorphism and/or STI. - # - # When testing these, we need to make sure it works via loading the association directly, or - # joining the association, or including the association. We also need to ensure that associations - # are readonly where relevant. - - # has_many through - # Source: has_many through - # Through: has_many - def test_has_many_through_has_many_with_has_many_through_source_reflection - general = tags(:general) - - assert_equal [general, general], authors(:david).tags - - assert_includes_and_joins_equal( - Author.where('tags.id' => tags(:general).id), - [authors(:david)], :tags - ) - - # This ensures that the polymorphism of taggings is being observed correctly - authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel') - assert authors.empty? - - authors = assert_queries(5) { Author.includes(:tags).to_a } - assert_no_queries do - assert_equal [general, general], authors.first.tags - end - end - - # has_many through - # Source: has_many - # Through: has_many through - def test_has_many_through_has_many_through_with_has_many_source_reflection - luke, david = subscribers(:first), subscribers(:second) - - author = authors(:david) - assert_equal [luke, david, david], author.subscribers.order('subscribers.nick') - - # All authors with subscribers where one of the subscribers' nick is 'alterself' - assert_includes_and_joins_equal( - Author.where('subscribers.nick' => 'alterself'), - [authors(:david)], :subscribers - ) - - authors = assert_queries(4) { Author.includes(:subscribers).to_a } - assert_no_queries do - assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick) - end - end - - # has_many through - # Source: has_one through - # Through: has_one - def test_has_many_through_has_one_with_has_one_through_source_reflection - founding = member_types(:founding) - - assert_equal [founding], members(:groucho).nested_member_types - - assert_includes_and_joins_equal( - Member.where('member_types.id' => founding.id), - [members(:groucho)], :nested_member_types - ) - - members = assert_queries(4) { Member.includes(:nested_member_types).to_a } - assert_no_queries do - assert_equal [founding], members.first.nested_member_types - end - end - - # has_many through - # Source: has_one - # Through: has_one through - def test_has_many_through_has_one_through_with_has_one_source_reflection - mustache = sponsors(:moustache_club_sponsor_for_groucho) - - assert_equal [mustache], members(:groucho).nested_sponsors - - assert_includes_and_joins_equal( - Member.where('sponsors.id' => mustache.id), - [members(:groucho)], :nested_sponsors - ) - - members = assert_queries(4) { Member.includes(:nested_sponsors).to_a } - assert_no_queries do - assert_equal [mustache], members.first.nested_sponsors - end - end - - # has_many through - # Source: has_many through - # Through: has_one - def test_has_many_through_has_one_with_has_many_through_source_reflection - groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) - - assert_equal [groucho_details, other_details], - members(:groucho).organization_member_details.order('member_details.id') - - assert_includes_and_joins_equal( - Member.where('member_details.id' => member_details(:groucho).id).order('member_details.id'), - [members(:groucho), members(:some_other_guy)], :organization_member_details - ) - - members = Member.joins(:organization_member_details). - where('member_details.id' => 9) - assert members.empty? - - members = assert_queries(4) { Member.includes(:organization_member_details).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal [groucho_details, other_details], members.first.organization_member_details.sort_by(&:id) - end - end - - # has_many through - # Source: has_many - # Through: has_one through - def test_has_many_through_has_one_through_with_has_many_source_reflection - groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) - - assert_equal [groucho_details, other_details], - members(:groucho).organization_member_details_2.order('member_details.id') - - assert_includes_and_joins_equal( - Member.where('member_details.id' => groucho_details.id).order('member_details.id'), - [members(:groucho), members(:some_other_guy)], :organization_member_details_2 - ) - - members = Member.joins(:organization_member_details_2). - where('member_details.id' => 9) - assert members.empty? - - members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal [groucho_details, other_details], members.first.organization_member_details_2.sort_by(&:id) - end - end - - # has_many through - # Source: has_and_belongs_to_many - # Through: has_many - def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection - general, cooking = categories(:general), categories(:cooking) - - assert_equal [general, cooking], authors(:bob).post_categories.order('categories.id') - - assert_includes_and_joins_equal( - Author.where('categories.id' => cooking.id), - [authors(:bob)], :post_categories - ) - - authors = assert_queries(3) { Author.includes(:post_categories).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal [general, cooking], authors[2].post_categories.sort_by(&:id) - end - end - - # has_many through - # Source: has_many - # Through: has_and_belongs_to_many - def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection - greetings, more = comments(:greetings), comments(:more_greetings) - - assert_equal [greetings, more], categories(:technology).post_comments.order('comments.id') - - assert_includes_and_joins_equal( - Category.where('comments.id' => more.id).order('comments.id'), - [categories(:general), categories(:technology)], :post_comments - ) - - categories = assert_queries(3) { Category.includes(:post_comments).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal [greetings, more], categories[1].post_comments.sort_by(&:id) - end - end - - # has_many through - # Source: has_many through a habtm - # Through: has_many through - def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection - greetings, more = comments(:greetings), comments(:more_greetings) - - assert_equal [greetings, more], authors(:bob).category_post_comments.order('comments.id') - - assert_includes_and_joins_equal( - Author.where('comments.id' => comments(:does_it_hurt).id).order('comments.id'), - [authors(:david), authors(:mary)], :category_post_comments - ) - - authors = assert_queries(5) { Author.includes(:category_post_comments).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal [greetings, more], authors[2].category_post_comments.sort_by(&:id) - end - end - - # has_many through - # Source: belongs_to - # Through: has_many through - def test_has_many_through_has_many_through_with_belongs_to_source_reflection - general = tags(:general) - - assert_equal [general, general], authors(:david).tagging_tags - - assert_includes_and_joins_equal( - Author.where('tags.id' => tags(:general).id), - [authors(:david)], :tagging_tags - ) - - authors = assert_queries(5) { Author.includes(:tagging_tags).to_a } - assert_no_queries do - assert_equal [general, general], authors.first.tagging_tags - end - end - - # has_many through - # Source: has_many through - # Through: belongs_to - def test_has_many_through_belongs_to_with_has_many_through_source_reflection - welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general) - - assert_equal [welcome_general, thinking_general], - categorizations(:david_welcome_general).post_taggings.order('taggings.id') - - assert_includes_and_joins_equal( - Categorization.where('taggings.id' => welcome_general.id).order('taggings.id'), - [categorizations(:david_welcome_general)], :post_taggings - ) - - categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings.sort_by(&:id) - end - end - - # has_one through - # Source: has_one through - # Through: has_one - def test_has_one_through_has_one_with_has_one_through_source_reflection - founding = member_types(:founding) - - assert_equal founding, members(:groucho).nested_member_type - - assert_includes_and_joins_equal( - Member.where('member_types.id' => founding.id), - [members(:groucho)], :nested_member_type - ) - - members = assert_queries(4) { Member.includes(:nested_member_type).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal founding, members.first.nested_member_type - end - end - - # has_one through - # Source: belongs_to - # Through: has_one through - def test_has_one_through_has_one_through_with_belongs_to_source_reflection - general = categories(:general) - - assert_equal general, members(:groucho).club_category - - assert_includes_and_joins_equal( - Member.where('categories.id' => categories(:technology).id), - [members(:blarpy_winkup)], :club_category - ) - - members = assert_queries(4) { Member.includes(:club_category).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal general, members.first.club_category - end - end - - def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection - author = authors(:david) - assert_equal [tags(:general)], author.distinct_tags - end - - def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection - author = authors(:david) - assert_equal [subscribers(:first), subscribers(:second)], - author.distinct_subscribers.order('subscribers.nick') - end - - def test_nested_has_many_through_with_a_table_referenced_multiple_times - author = authors(:bob) - assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)], - author.similar_posts.sort_by(&:id) - - # Mary and Bob both have posts in misc, but they are the only ones. - authors = Author.joins(:similar_posts).where('posts.id' => posts(:misc_by_bob).id) - assert_equal [authors(:mary), authors(:bob)], authors.uniq.sort_by(&:id) - - # Check the polymorphism of taggings is being observed correctly (in both joins) - authors = Author.joins(:similar_posts).where('taggings.taggable_type' => 'FakeModel') - assert authors.empty? - authors = Author.joins(:similar_posts).where('taggings_authors_join.taggable_type' => 'FakeModel') - assert authors.empty? - end - - def test_has_many_through_with_foreign_key_option_on_through_reflection - assert_equal [posts(:welcome), posts(:authorless)], people(:david).agents_posts.order('posts.id') - assert_equal [authors(:david)], references(:david_unicyclist).agents_posts_authors - - references = Reference.joins(:agents_posts_authors).where('authors.id' => authors(:david).id) - assert_equal [references(:david_unicyclist)], references - end - - def test_has_many_through_with_foreign_key_option_on_source_reflection - assert_equal [people(:michael), people(:susan)], jobs(:unicyclist).agents.order('people.id') - - jobs = Job.joins(:agents) - assert_equal [jobs(:unicyclist), jobs(:unicyclist)], jobs - end - - def test_has_many_through_with_sti_on_through_reflection - ratings = posts(:sti_comments).special_comments_ratings.sort_by(&:id) - assert_equal [ratings(:special_comment_rating), ratings(:sub_special_comment_rating)], ratings - - # Ensure STI is respected in the join - scope = Post.joins(:special_comments_ratings).where(:id => posts(:sti_comments).id) - assert scope.where("comments.type" => "Comment").empty? - assert !scope.where("comments.type" => "SpecialComment").empty? - assert !scope.where("comments.type" => "SubSpecialComment").empty? - end - - def test_nested_has_many_through_writers_should_raise_error - david = authors(:david) - subscriber = subscribers(:first) - - assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do - david.subscribers = [subscriber] - end - - assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do - david.subscriber_ids = [subscriber.id] - end - - assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do - david.subscribers << subscriber - end - - assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do - david.subscribers.delete(subscriber) - end - - assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do - david.subscribers.clear - end - - assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do - david.subscribers.build - end - - assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do - david.subscribers.create - end - end - - def test_nested_has_one_through_writers_should_raise_error - groucho = members(:groucho) - founding = member_types(:founding) - - assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do - groucho.nested_member_type = founding - end - end - - def test_nested_has_many_through_with_conditions_on_through_associations - blue, bob = tags(:blue), authors(:bob) - - assert_equal [blue], bob.misc_post_first_blue_tags - - # Pointless condition to force single-query loading - assert_includes_and_joins_equal( - Author.where('tags.id = tags.id'), - [bob], :misc_post_first_blue_tags - ) - - assert Author.where('tags.id' => 100).joins(:misc_post_first_blue_tags).empty? - - authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal [blue], authors[2].misc_post_first_blue_tags - end - end - - def test_nested_has_many_through_with_conditions_on_source_associations - blue, bob = tags(:blue), authors(:bob) - - assert_equal [blue], bob.misc_post_first_blue_tags_2 - - # Pointless condition to force single-query loading - assert_includes_and_joins_equal( - Author.where('tags.id = tags.id'), - [bob], :misc_post_first_blue_tags_2 - ) - - authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) } - assert_no_queries do - assert_equal [blue], authors[2].misc_post_first_blue_tags_2 - end - end - - def test_nested_has_many_through_with_foreign_key_option_on_the_source_reflection_through_reflection - assert_equal [categories(:general)], organizations(:nsa).author_essay_categories - - organizations = Organization.joins(:author_essay_categories). - where('categories.id' => categories(:general).id) - assert_equal [organizations(:nsa)], organizations - - assert_equal categories(:general), organizations(:nsa).author_owned_essay_category - - organizations = Organization.joins(:author_owned_essay_category). - where('categories.id' => categories(:general).id) - assert_equal [organizations(:nsa)], organizations - end - - private - - def assert_includes_and_joins_equal(query, expected, association) - actual = assert_queries(1) { query.joins(association).to_a.uniq } - assert_equal expected, actual - - actual = assert_queries(1) { query.includes(association).to_a.uniq } - assert_equal expected, actual - end -end diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb new file mode 100644 index 0000000000..bfc290e877 --- /dev/null +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -0,0 +1,467 @@ +require "cases/helper" +require 'models/author' +require 'models/post' +require 'models/person' +require 'models/reference' +require 'models/job' +require 'models/reader' +require 'models/comment' +require 'models/tag' +require 'models/tagging' +require 'models/subscriber' +require 'models/book' +require 'models/subscription' +require 'models/rating' +require 'models/member' +require 'models/member_detail' +require 'models/member_type' +require 'models/sponsor' +require 'models/club' +require 'models/organization' +require 'models/category' +require 'models/categorization' +require 'models/membership' +require 'models/essay' + +class NestedThroughAssociationsTest < ActiveRecord::TestCase + fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings, + :people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details, + :member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts, + :categorizations, :memberships, :essays + + # Through associations can either use the has_many or has_one macros. + # + # has_many + # - Source reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many + # - Through reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many + # + # has_one + # - Source reflection can be has_one or belongs_to + # - Through reflection can be has_one or belongs_to + # + # Additionally, the source reflection and/or through reflection may be subject to + # polymorphism and/or STI. + # + # When testing these, we need to make sure it works via loading the association directly, or + # joining the association, or including the association. We also need to ensure that associations + # are readonly where relevant. + + # has_many through + # Source: has_many through + # Through: has_many + def test_has_many_through_has_many_with_has_many_through_source_reflection + general = tags(:general) + + assert_equal [general, general], authors(:david).tags + + assert_includes_and_joins_equal( + Author.where('tags.id' => tags(:general).id), + [authors(:david)], :tags + ) + + # This ensures that the polymorphism of taggings is being observed correctly + authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel') + assert authors.empty? + + authors = assert_queries(5) { Author.includes(:tags).to_a } + assert_no_queries do + assert_equal [general, general], authors.first.tags + end + end + + # has_many through + # Source: has_many + # Through: has_many through + def test_has_many_through_has_many_through_with_has_many_source_reflection + luke, david = subscribers(:first), subscribers(:second) + + author = authors(:david) + assert_equal [luke, david, david], author.subscribers.order('subscribers.nick') + + # All authors with subscribers where one of the subscribers' nick is 'alterself' + assert_includes_and_joins_equal( + Author.where('subscribers.nick' => 'alterself'), + [authors(:david)], :subscribers + ) + + authors = assert_queries(4) { Author.includes(:subscribers).to_a } + assert_no_queries do + assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick) + end + end + + # has_many through + # Source: has_one through + # Through: has_one + def test_has_many_through_has_one_with_has_one_through_source_reflection + founding = member_types(:founding) + + assert_equal [founding], members(:groucho).nested_member_types + + assert_includes_and_joins_equal( + Member.where('member_types.id' => founding.id), + [members(:groucho)], :nested_member_types + ) + + members = assert_queries(4) { Member.includes(:nested_member_types).to_a } + assert_no_queries do + assert_equal [founding], members.first.nested_member_types + end + end + + # has_many through + # Source: has_one + # Through: has_one through + def test_has_many_through_has_one_through_with_has_one_source_reflection + mustache = sponsors(:moustache_club_sponsor_for_groucho) + + assert_equal [mustache], members(:groucho).nested_sponsors + + assert_includes_and_joins_equal( + Member.where('sponsors.id' => mustache.id), + [members(:groucho)], :nested_sponsors + ) + + members = assert_queries(4) { Member.includes(:nested_sponsors).to_a } + assert_no_queries do + assert_equal [mustache], members.first.nested_sponsors + end + end + + # has_many through + # Source: has_many through + # Through: has_one + def test_has_many_through_has_one_with_has_many_through_source_reflection + groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) + + assert_equal [groucho_details, other_details], + members(:groucho).organization_member_details.order('member_details.id') + + assert_includes_and_joins_equal( + Member.where('member_details.id' => member_details(:groucho).id).order('member_details.id'), + [members(:groucho), members(:some_other_guy)], :organization_member_details + ) + + members = Member.joins(:organization_member_details). + where('member_details.id' => 9) + assert members.empty? + + members = assert_queries(4) { Member.includes(:organization_member_details).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal [groucho_details, other_details], members.first.organization_member_details.sort_by(&:id) + end + end + + # has_many through + # Source: has_many + # Through: has_one through + def test_has_many_through_has_one_through_with_has_many_source_reflection + groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) + + assert_equal [groucho_details, other_details], + members(:groucho).organization_member_details_2.order('member_details.id') + + assert_includes_and_joins_equal( + Member.where('member_details.id' => groucho_details.id).order('member_details.id'), + [members(:groucho), members(:some_other_guy)], :organization_member_details_2 + ) + + members = Member.joins(:organization_member_details_2). + where('member_details.id' => 9) + assert members.empty? + + members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal [groucho_details, other_details], members.first.organization_member_details_2.sort_by(&:id) + end + end + + # has_many through + # Source: has_and_belongs_to_many + # Through: has_many + def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection + general, cooking = categories(:general), categories(:cooking) + + assert_equal [general, cooking], authors(:bob).post_categories.order('categories.id') + + assert_includes_and_joins_equal( + Author.where('categories.id' => cooking.id), + [authors(:bob)], :post_categories + ) + + authors = assert_queries(3) { Author.includes(:post_categories).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal [general, cooking], authors[2].post_categories.sort_by(&:id) + end + end + + # has_many through + # Source: has_many + # Through: has_and_belongs_to_many + def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection + greetings, more = comments(:greetings), comments(:more_greetings) + + assert_equal [greetings, more], categories(:technology).post_comments.order('comments.id') + + assert_includes_and_joins_equal( + Category.where('comments.id' => more.id).order('comments.id'), + [categories(:general), categories(:technology)], :post_comments + ) + + categories = assert_queries(3) { Category.includes(:post_comments).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal [greetings, more], categories[1].post_comments.sort_by(&:id) + end + end + + # has_many through + # Source: has_many through a habtm + # Through: has_many through + def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection + greetings, more = comments(:greetings), comments(:more_greetings) + + assert_equal [greetings, more], authors(:bob).category_post_comments.order('comments.id') + + assert_includes_and_joins_equal( + Author.where('comments.id' => comments(:does_it_hurt).id).order('comments.id'), + [authors(:david), authors(:mary)], :category_post_comments + ) + + authors = assert_queries(5) { Author.includes(:category_post_comments).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal [greetings, more], authors[2].category_post_comments.sort_by(&:id) + end + end + + # has_many through + # Source: belongs_to + # Through: has_many through + def test_has_many_through_has_many_through_with_belongs_to_source_reflection + general = tags(:general) + + assert_equal [general, general], authors(:david).tagging_tags + + assert_includes_and_joins_equal( + Author.where('tags.id' => tags(:general).id), + [authors(:david)], :tagging_tags + ) + + authors = assert_queries(5) { Author.includes(:tagging_tags).to_a } + assert_no_queries do + assert_equal [general, general], authors.first.tagging_tags + end + end + + # has_many through + # Source: has_many through + # Through: belongs_to + def test_has_many_through_belongs_to_with_has_many_through_source_reflection + welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general) + + assert_equal [welcome_general, thinking_general], + categorizations(:david_welcome_general).post_taggings.order('taggings.id') + + assert_includes_and_joins_equal( + Categorization.where('taggings.id' => welcome_general.id).order('taggings.id'), + [categorizations(:david_welcome_general)], :post_taggings + ) + + categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings.sort_by(&:id) + end + end + + # has_one through + # Source: has_one through + # Through: has_one + def test_has_one_through_has_one_with_has_one_through_source_reflection + founding = member_types(:founding) + + assert_equal founding, members(:groucho).nested_member_type + + assert_includes_and_joins_equal( + Member.where('member_types.id' => founding.id), + [members(:groucho)], :nested_member_type + ) + + members = assert_queries(4) { Member.includes(:nested_member_type).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal founding, members.first.nested_member_type + end + end + + # has_one through + # Source: belongs_to + # Through: has_one through + def test_has_one_through_has_one_through_with_belongs_to_source_reflection + general = categories(:general) + + assert_equal general, members(:groucho).club_category + + assert_includes_and_joins_equal( + Member.where('categories.id' => categories(:technology).id), + [members(:blarpy_winkup)], :club_category + ) + + members = assert_queries(4) { Member.includes(:club_category).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal general, members.first.club_category + end + end + + def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection + author = authors(:david) + assert_equal [tags(:general)], author.distinct_tags + end + + def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection + author = authors(:david) + assert_equal [subscribers(:first), subscribers(:second)], + author.distinct_subscribers.order('subscribers.nick') + end + + def test_nested_has_many_through_with_a_table_referenced_multiple_times + author = authors(:bob) + assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)], + author.similar_posts.sort_by(&:id) + + # Mary and Bob both have posts in misc, but they are the only ones. + authors = Author.joins(:similar_posts).where('posts.id' => posts(:misc_by_bob).id) + assert_equal [authors(:mary), authors(:bob)], authors.uniq.sort_by(&:id) + + # Check the polymorphism of taggings is being observed correctly (in both joins) + authors = Author.joins(:similar_posts).where('taggings.taggable_type' => 'FakeModel') + assert authors.empty? + authors = Author.joins(:similar_posts).where('taggings_authors_join.taggable_type' => 'FakeModel') + assert authors.empty? + end + + def test_has_many_through_with_foreign_key_option_on_through_reflection + assert_equal [posts(:welcome), posts(:authorless)], people(:david).agents_posts.order('posts.id') + assert_equal [authors(:david)], references(:david_unicyclist).agents_posts_authors + + references = Reference.joins(:agents_posts_authors).where('authors.id' => authors(:david).id) + assert_equal [references(:david_unicyclist)], references + end + + def test_has_many_through_with_foreign_key_option_on_source_reflection + assert_equal [people(:michael), people(:susan)], jobs(:unicyclist).agents.order('people.id') + + jobs = Job.joins(:agents) + assert_equal [jobs(:unicyclist), jobs(:unicyclist)], jobs + end + + def test_has_many_through_with_sti_on_through_reflection + ratings = posts(:sti_comments).special_comments_ratings.sort_by(&:id) + assert_equal [ratings(:special_comment_rating), ratings(:sub_special_comment_rating)], ratings + + # Ensure STI is respected in the join + scope = Post.joins(:special_comments_ratings).where(:id => posts(:sti_comments).id) + assert scope.where("comments.type" => "Comment").empty? + assert !scope.where("comments.type" => "SpecialComment").empty? + assert !scope.where("comments.type" => "SubSpecialComment").empty? + end + + def test_nested_has_many_through_writers_should_raise_error + david = authors(:david) + subscriber = subscribers(:first) + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers = [subscriber] + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscriber_ids = [subscriber.id] + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers << subscriber + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers.delete(subscriber) + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers.clear + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers.build + end + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + david.subscribers.create + end + end + + def test_nested_has_one_through_writers_should_raise_error + groucho = members(:groucho) + founding = member_types(:founding) + + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do + groucho.nested_member_type = founding + end + end + + def test_nested_has_many_through_with_conditions_on_through_associations + blue, bob = tags(:blue), authors(:bob) + + assert_equal [blue], bob.misc_post_first_blue_tags + + # Pointless condition to force single-query loading + assert_includes_and_joins_equal( + Author.where('tags.id = tags.id'), + [bob], :misc_post_first_blue_tags + ) + + assert Author.where('tags.id' => 100).joins(:misc_post_first_blue_tags).empty? + + authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal [blue], authors[2].misc_post_first_blue_tags + end + end + + def test_nested_has_many_through_with_conditions_on_source_associations + blue, bob = tags(:blue), authors(:bob) + + assert_equal [blue], bob.misc_post_first_blue_tags_2 + + # Pointless condition to force single-query loading + assert_includes_and_joins_equal( + Author.where('tags.id = tags.id'), + [bob], :misc_post_first_blue_tags_2 + ) + + authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) } + assert_no_queries do + assert_equal [blue], authors[2].misc_post_first_blue_tags_2 + end + end + + def test_nested_has_many_through_with_foreign_key_option_on_the_source_reflection_through_reflection + assert_equal [categories(:general)], organizations(:nsa).author_essay_categories + + organizations = Organization.joins(:author_essay_categories). + where('categories.id' => categories(:general).id) + assert_equal [organizations(:nsa)], organizations + + assert_equal categories(:general), organizations(:nsa).author_owned_essay_category + + organizations = Organization.joins(:author_owned_essay_category). + where('categories.id' => categories(:general).id) + assert_equal [organizations(:nsa)], organizations + end + + private + + def assert_includes_and_joins_equal(query, expected, association) + actual = assert_queries(1) { query.joins(association).to_a.uniq } + assert_equal expected, actual + + actual = assert_queries(1) { query.includes(association).to_a.uniq } + assert_equal expected, actual + end +end -- cgit v1.2.3 From 9a1a32ac2b8a526f543367bc7e8258bbd7e6a164 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 31 Oct 2010 11:21:28 +0000 Subject: Fix naughty trailing whitespace --- .../has_many_through_associations_test.rb | 10 +- .../has_one_through_associations_test.rb | 12 +- .../nested_through_associations_test.rb | 180 ++++++++++----------- 3 files changed, 101 insertions(+), 101 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 713c492f5e..4e398751d2 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -456,19 +456,19 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_polymorphic_with_primary_key_option assert_equal [categories(:general)], authors(:david).essay_categories - + authors = Author.joins(:essay_categories).where('categories.id' => categories(:general).id) assert_equal authors(:david), authors.first - + assert_equal [owners(:blackbeard)], authors(:david).essay_owners - + authors = Author.joins(:essay_owners).where("owners.name = 'blackbeard'") assert_equal authors(:david), authors.first end - + def test_has_many_through_with_primary_key_option assert_equal [categories(:general)], authors(:david).essay_categories_2 - + authors = Author.joins(:essay_categories_2).where('categories.id' => categories(:general).id) assert_equal authors(:david), authors.first end diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index 39e14b4bfd..1cf8c0539d 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -217,22 +217,22 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase minivan.dashboard end end - + def test_has_one_through_polymorphic_with_primary_key_option assert_equal categories(:general), authors(:david).essay_category - + authors = Author.joins(:essay_category).where('categories.id' => categories(:general).id) assert_equal authors(:david), authors.first - + assert_equal owners(:blackbeard), authors(:david).essay_owner - + authors = Author.joins(:essay_owner).where("owners.name = 'blackbeard'") assert_equal authors(:david), authors.first end - + def test_has_one_through_with_primary_key_option assert_equal categories(:general), authors(:david).essay_category_2 - + authors = Author.joins(:essay_category_2).where('categories.id' => categories(:general).id) assert_equal authors(:david), authors.first end diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index bfc290e877..db7c8b6c45 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -30,18 +30,18 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase :categorizations, :memberships, :essays # Through associations can either use the has_many or has_one macros. - # + # # has_many # - Source reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many # - Through reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many - # + # # has_one # - Source reflection can be has_one or belongs_to # - Through reflection can be has_one or belongs_to - # + # # Additionally, the source reflection and/or through reflection may be subject to # polymorphism and/or STI. - # + # # When testing these, we need to make sure it works via loading the association directly, or # joining the association, or including the association. We also need to ensure that associations # are readonly where relevant. @@ -51,18 +51,18 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase # Through: has_many def test_has_many_through_has_many_with_has_many_through_source_reflection general = tags(:general) - + assert_equal [general, general], authors(:david).tags - + assert_includes_and_joins_equal( Author.where('tags.id' => tags(:general).id), [authors(:david)], :tags ) - + # This ensures that the polymorphism of taggings is being observed correctly authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel') assert authors.empty? - + authors = assert_queries(5) { Author.includes(:tags).to_a } assert_no_queries do assert_equal [general, general], authors.first.tags @@ -74,236 +74,236 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase # Through: has_many through def test_has_many_through_has_many_through_with_has_many_source_reflection luke, david = subscribers(:first), subscribers(:second) - + author = authors(:david) assert_equal [luke, david, david], author.subscribers.order('subscribers.nick') - + # All authors with subscribers where one of the subscribers' nick is 'alterself' assert_includes_and_joins_equal( Author.where('subscribers.nick' => 'alterself'), [authors(:david)], :subscribers ) - + authors = assert_queries(4) { Author.includes(:subscribers).to_a } assert_no_queries do assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick) end end - + # has_many through # Source: has_one through # Through: has_one def test_has_many_through_has_one_with_has_one_through_source_reflection founding = member_types(:founding) - + assert_equal [founding], members(:groucho).nested_member_types - + assert_includes_and_joins_equal( Member.where('member_types.id' => founding.id), [members(:groucho)], :nested_member_types ) - + members = assert_queries(4) { Member.includes(:nested_member_types).to_a } assert_no_queries do assert_equal [founding], members.first.nested_member_types end end - + # has_many through # Source: has_one # Through: has_one through def test_has_many_through_has_one_through_with_has_one_source_reflection mustache = sponsors(:moustache_club_sponsor_for_groucho) - + assert_equal [mustache], members(:groucho).nested_sponsors - + assert_includes_and_joins_equal( Member.where('sponsors.id' => mustache.id), [members(:groucho)], :nested_sponsors ) - + members = assert_queries(4) { Member.includes(:nested_sponsors).to_a } assert_no_queries do assert_equal [mustache], members.first.nested_sponsors end end - + # has_many through # Source: has_many through # Through: has_one def test_has_many_through_has_one_with_has_many_through_source_reflection groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) - + assert_equal [groucho_details, other_details], members(:groucho).organization_member_details.order('member_details.id') - + assert_includes_and_joins_equal( Member.where('member_details.id' => member_details(:groucho).id).order('member_details.id'), [members(:groucho), members(:some_other_guy)], :organization_member_details ) - + members = Member.joins(:organization_member_details). where('member_details.id' => 9) assert members.empty? - + members = assert_queries(4) { Member.includes(:organization_member_details).to_a.sort_by(&:id) } assert_no_queries do assert_equal [groucho_details, other_details], members.first.organization_member_details.sort_by(&:id) end end - + # has_many through # Source: has_many # Through: has_one through def test_has_many_through_has_one_through_with_has_many_source_reflection groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) - + assert_equal [groucho_details, other_details], members(:groucho).organization_member_details_2.order('member_details.id') - + assert_includes_and_joins_equal( Member.where('member_details.id' => groucho_details.id).order('member_details.id'), [members(:groucho), members(:some_other_guy)], :organization_member_details_2 ) - + members = Member.joins(:organization_member_details_2). where('member_details.id' => 9) assert members.empty? - + members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a.sort_by(&:id) } assert_no_queries do assert_equal [groucho_details, other_details], members.first.organization_member_details_2.sort_by(&:id) end end - + # has_many through # Source: has_and_belongs_to_many # Through: has_many def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection general, cooking = categories(:general), categories(:cooking) - + assert_equal [general, cooking], authors(:bob).post_categories.order('categories.id') - + assert_includes_and_joins_equal( Author.where('categories.id' => cooking.id), [authors(:bob)], :post_categories ) - + authors = assert_queries(3) { Author.includes(:post_categories).to_a.sort_by(&:id) } assert_no_queries do assert_equal [general, cooking], authors[2].post_categories.sort_by(&:id) end end - + # has_many through # Source: has_many # Through: has_and_belongs_to_many def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection greetings, more = comments(:greetings), comments(:more_greetings) - + assert_equal [greetings, more], categories(:technology).post_comments.order('comments.id') - + assert_includes_and_joins_equal( Category.where('comments.id' => more.id).order('comments.id'), [categories(:general), categories(:technology)], :post_comments ) - + categories = assert_queries(3) { Category.includes(:post_comments).to_a.sort_by(&:id) } assert_no_queries do assert_equal [greetings, more], categories[1].post_comments.sort_by(&:id) end end - + # has_many through # Source: has_many through a habtm # Through: has_many through def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection greetings, more = comments(:greetings), comments(:more_greetings) - + assert_equal [greetings, more], authors(:bob).category_post_comments.order('comments.id') - + assert_includes_and_joins_equal( Author.where('comments.id' => comments(:does_it_hurt).id).order('comments.id'), [authors(:david), authors(:mary)], :category_post_comments ) - + authors = assert_queries(5) { Author.includes(:category_post_comments).to_a.sort_by(&:id) } assert_no_queries do assert_equal [greetings, more], authors[2].category_post_comments.sort_by(&:id) end end - + # has_many through # Source: belongs_to # Through: has_many through def test_has_many_through_has_many_through_with_belongs_to_source_reflection general = tags(:general) - + assert_equal [general, general], authors(:david).tagging_tags - + assert_includes_and_joins_equal( Author.where('tags.id' => tags(:general).id), [authors(:david)], :tagging_tags ) - + authors = assert_queries(5) { Author.includes(:tagging_tags).to_a } assert_no_queries do assert_equal [general, general], authors.first.tagging_tags end end - + # has_many through # Source: has_many through # Through: belongs_to def test_has_many_through_belongs_to_with_has_many_through_source_reflection welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general) - + assert_equal [welcome_general, thinking_general], categorizations(:david_welcome_general).post_taggings.order('taggings.id') - + assert_includes_and_joins_equal( Categorization.where('taggings.id' => welcome_general.id).order('taggings.id'), [categorizations(:david_welcome_general)], :post_taggings ) - + categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a.sort_by(&:id) } assert_no_queries do assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings.sort_by(&:id) end end - + # has_one through # Source: has_one through # Through: has_one def test_has_one_through_has_one_with_has_one_through_source_reflection founding = member_types(:founding) - + assert_equal founding, members(:groucho).nested_member_type - + assert_includes_and_joins_equal( Member.where('member_types.id' => founding.id), [members(:groucho)], :nested_member_type ) - + members = assert_queries(4) { Member.includes(:nested_member_type).to_a.sort_by(&:id) } assert_no_queries do assert_equal founding, members.first.nested_member_type end end - + # has_one through # Source: belongs_to # Through: has_one through def test_has_one_through_has_one_through_with_belongs_to_source_reflection general = categories(:general) - + assert_equal general, members(:groucho).club_category - + assert_includes_and_joins_equal( Member.where('categories.id' => categories(:technology).id), [members(:blarpy_winkup)], :club_category ) - + members = assert_queries(4) { Member.includes(:club_category).to_a.sort_by(&:id) } assert_no_queries do assert_equal general, members.first.club_category @@ -320,34 +320,34 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase assert_equal [subscribers(:first), subscribers(:second)], author.distinct_subscribers.order('subscribers.nick') end - + def test_nested_has_many_through_with_a_table_referenced_multiple_times author = authors(:bob) assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)], author.similar_posts.sort_by(&:id) - + # Mary and Bob both have posts in misc, but they are the only ones. authors = Author.joins(:similar_posts).where('posts.id' => posts(:misc_by_bob).id) assert_equal [authors(:mary), authors(:bob)], authors.uniq.sort_by(&:id) - + # Check the polymorphism of taggings is being observed correctly (in both joins) authors = Author.joins(:similar_posts).where('taggings.taggable_type' => 'FakeModel') assert authors.empty? authors = Author.joins(:similar_posts).where('taggings_authors_join.taggable_type' => 'FakeModel') assert authors.empty? end - + def test_has_many_through_with_foreign_key_option_on_through_reflection assert_equal [posts(:welcome), posts(:authorless)], people(:david).agents_posts.order('posts.id') assert_equal [authors(:david)], references(:david_unicyclist).agents_posts_authors - + references = Reference.joins(:agents_posts_authors).where('authors.id' => authors(:david).id) assert_equal [references(:david_unicyclist)], references end - + def test_has_many_through_with_foreign_key_option_on_source_reflection assert_equal [people(:michael), people(:susan)], jobs(:unicyclist).agents.order('people.id') - + jobs = Job.joins(:agents) assert_equal [jobs(:unicyclist), jobs(:unicyclist)], jobs end @@ -355,7 +355,7 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_with_sti_on_through_reflection ratings = posts(:sti_comments).special_comments_ratings.sort_by(&:id) assert_equal [ratings(:special_comment_rating), ratings(:sub_special_comment_rating)], ratings - + # Ensure STI is respected in the join scope = Post.joins(:special_comments_ratings).where(:id => posts(:sti_comments).id) assert scope.where("comments.type" => "Comment").empty? @@ -366,101 +366,101 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase def test_nested_has_many_through_writers_should_raise_error david = authors(:david) subscriber = subscribers(:first) - + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do david.subscribers = [subscriber] end - + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do david.subscriber_ids = [subscriber.id] end - + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do david.subscribers << subscriber end - + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do david.subscribers.delete(subscriber) end - + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do david.subscribers.clear end - + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do david.subscribers.build end - + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do david.subscribers.create end end - + def test_nested_has_one_through_writers_should_raise_error groucho = members(:groucho) founding = member_types(:founding) - + assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do groucho.nested_member_type = founding end end - + def test_nested_has_many_through_with_conditions_on_through_associations blue, bob = tags(:blue), authors(:bob) - + assert_equal [blue], bob.misc_post_first_blue_tags - + # Pointless condition to force single-query loading assert_includes_and_joins_equal( Author.where('tags.id = tags.id'), [bob], :misc_post_first_blue_tags ) - + assert Author.where('tags.id' => 100).joins(:misc_post_first_blue_tags).empty? - + authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a.sort_by(&:id) } assert_no_queries do assert_equal [blue], authors[2].misc_post_first_blue_tags end end - + def test_nested_has_many_through_with_conditions_on_source_associations blue, bob = tags(:blue), authors(:bob) - + assert_equal [blue], bob.misc_post_first_blue_tags_2 - + # Pointless condition to force single-query loading assert_includes_and_joins_equal( Author.where('tags.id = tags.id'), [bob], :misc_post_first_blue_tags_2 ) - + authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) } assert_no_queries do assert_equal [blue], authors[2].misc_post_first_blue_tags_2 end end - + def test_nested_has_many_through_with_foreign_key_option_on_the_source_reflection_through_reflection assert_equal [categories(:general)], organizations(:nsa).author_essay_categories - + organizations = Organization.joins(:author_essay_categories). where('categories.id' => categories(:general).id) assert_equal [organizations(:nsa)], organizations - + assert_equal categories(:general), organizations(:nsa).author_owned_essay_category - + organizations = Organization.joins(:author_owned_essay_category). where('categories.id' => categories(:general).id) assert_equal [organizations(:nsa)], organizations end - + private - + def assert_includes_and_joins_equal(query, expected, association) actual = assert_queries(1) { query.joins(association).to_a.uniq } assert_equal expected, actual - + actual = assert_queries(1) { query.includes(association).to_a.uniq } assert_equal expected, actual end -- cgit v1.2.3 From 026dbd28d9dbaddb7cdd7d6fdc1349cc2f43242f Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 31 Oct 2010 11:16:16 +0000 Subject: Fix bug with 0bb85ed9ffa9808926b46e8f7e59cab5b85ac19f which missed out a fixtures declaration in cascaded_eager_loading_test.rb --- activerecord/test/cases/associations/cascaded_eager_loading_test.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index 81e99036af..d997385266 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -10,7 +10,8 @@ require 'models/reply' require 'models/person' class CascadedEagerLoadingTest < ActiveRecord::TestCase - fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments, :categorizations, :people + fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments, + :categorizations, :people, :categories def test_eager_association_loading_with_cascaded_two_levels authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id") -- cgit v1.2.3 From 083d6f267611472b8acfb9801e64971ee6d19994 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 31 Oct 2010 11:27:58 +0000 Subject: Update new tests in cascaded_eager_loading_test.rb to work with the modified fixtures in this branch --- .../test/cases/associations/cascaded_eager_loading_test.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index d997385266..dbc3bcf758 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -51,24 +51,24 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase categories = Category.joins(:categorizations).includes([{:posts=>:comments}, :authors]) assert_nothing_raised do - assert_equal 2, categories.count - assert_equal 2, categories.all.uniq.size # Must uniq since instantiating with inner joins will get dupes + assert_equal 3, categories.count + assert_equal 3, categories.all.uniq.size # Must uniq since instantiating with inner joins will get dupes end end def test_cascaded_eager_association_loading_with_duplicated_includes categories = Category.includes(:categorizations).includes(:categorizations => :author).where("categorizations.id is not null") assert_nothing_raised do - assert_equal 2, categories.count - assert_equal 2, categories.all.size + assert_equal 3, categories.count + assert_equal 3, categories.all.size end end def test_cascaded_eager_association_loading_with_twice_includes_edge_cases categories = Category.includes(:categorizations => :author).includes(:categorizations => :post).where("posts.id is not null") assert_nothing_raised do - assert_equal 2, categories.count - assert_equal 2, categories.all.size + assert_equal 3, categories.count + assert_equal 3, categories.all.size end end -- cgit v1.2.3 From 73c0b390b3a1ea9487c3f667352463a90af6dd71 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 4 Mar 2011 22:29:40 +0000 Subject: When preloading has_and_belongs_to_many associations, we should only instantiate one AR object per actual record in the database. (Even when IM is off.) --- activerecord/test/cases/associations/eager_test.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index ed6337b596..40c82f2fb8 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -525,6 +525,22 @@ class EagerAssociationTest < ActiveRecord::TestCase assert posts[1].categories.include?(categories(:general)) end + # This is only really relevant when the identity map is off. Since the preloader for habtm + # gets raw row hashes from the database and then instantiates them, this test ensures that + # it only instantiates one actual object per record from the database. + def test_has_and_belongs_to_many_should_not_instantiate_same_records_multiple_times + welcome = posts(:welcome) + categories = Category.includes(:posts) + + general = categories.find { |c| c == categories(:general) } + technology = categories.find { |c| c == categories(:technology) } + + post1 = general.posts.to_a.find { |p| p == posts(:welcome) } + post2 = technology.posts.to_a.find { |p| p == posts(:welcome) } + + assert_equal post1.object_id, post2.object_id + end + def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers posts = authors(:david).posts.find(:all, :include => :comments, -- cgit v1.2.3 From ddf83d14f1c7ddae07a285a8ad7c45f652edc843 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sat, 5 Mar 2011 20:10:24 +0000 Subject: Add a test for STI on the through where the through is nested, and change the code which support this --- .../test/cases/associations/nested_through_associations_test.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index a4ac69782a..0dd407f342 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -425,6 +425,15 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase assert !scope.where("comments.type" => "SubSpecialComment").empty? end + def test_has_many_through_with_sti_on_nested_through_reflection + taggings = posts(:sti_comments).special_comments_ratings_taggings + assert_equal [taggings(:special_comment_rating)], taggings + + scope = Post.joins(:special_comments_ratings_taggings).where(:id => posts(:sti_comments).id) + assert scope.where("comments.type" => "Comment").empty? + assert !scope.where("comments.type" => "SpecialComment").empty? + end + def test_nested_has_many_through_writers_should_raise_error david = authors(:david) subscriber = subscribers(:first) -- cgit v1.2.3 From 37d93ea16046add35fecd8c279e868869ee744a5 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sat, 12 Mar 2011 09:32:20 +0000 Subject: Fix tests under postgres - we should always put conditions in the WHERE part not in ON constraints because postgres requires that the table has been joined before the condition references it. --- .../test/cases/associations/nested_through_associations_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index 0dd407f342..dd450a2a8e 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -272,7 +272,7 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload_via_joins assert_includes_and_joins_equal( - Author.where('comments.id' => comments(:does_it_hurt).id).order('comments.id'), + Author.where('comments.id' => comments(:does_it_hurt).id).order('authors.id'), [authors(:david), authors(:mary)], :category_post_comments ) end -- cgit v1.2.3 From 9abc94c44516afdcfe4a3b202c336c9578fd6d0d Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Wed, 16 Mar 2011 18:54:34 +0000 Subject: oracle, y u defy me --- activerecord/test/cases/associations/join_model_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index 543eff7d8b..f54d69e7fa 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -305,7 +305,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase end def test_has_many_through_with_custom_primary_key_on_has_many_source - assert_equal [authors(:david), authors(:bob)], posts(:thinking).authors_using_custom_pk.order(:id) + assert_equal [authors(:david), authors(:bob)], posts(:thinking).authors_using_custom_pk.order('authors.id') end def test_both_scoped_and_explicit_joins_should_be_respected -- cgit v1.2.3 From ed97c395178391c9083b20121cdd6606a9e92d14 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 22 Mar 2011 10:10:33 -0700 Subject: adding missing require --- activerecord/test/cases/associations/join_model_test.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'activerecord/test/cases/associations') diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index f54d69e7fa..1f95b31497 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -2,6 +2,7 @@ require "cases/helper" require 'models/tag' require 'models/tagging' require 'models/post' +require 'models/rating' require 'models/item' require 'models/comment' require 'models/author' -- cgit v1.2.3