aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2010-10-09 22:00:33 +0100
committerJon Leighton <j@jonathanleighton.com>2010-10-09 22:00:33 +0100
commitab5a9335020eff0da35b62b86a62ed8587a4d598 (patch)
tree1a1996c8844e359b88d5b30bf3531d22dba83d1b /activerecord/test
parentc954d54e2f36bb53ced5e3655adc071dd233797e (diff)
downloadrails-ab5a9335020eff0da35b62b86a62ed8587a4d598.tar.gz
rails-ab5a9335020eff0da35b62b86a62ed8587a4d598.tar.bz2
rails-ab5a9335020eff0da35b62b86a62ed8587a4d598.zip
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.
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/cases/associations/nested_has_many_through_associations_test.rb59
-rw-r--r--activerecord/test/fixtures/ratings.yml14
-rw-r--r--activerecord/test/models/comment.rb1
-rw-r--r--activerecord/test/models/job.rb2
-rw-r--r--activerecord/test/models/person.rb3
-rw-r--r--activerecord/test/models/post.rb2
-rw-r--r--activerecord/test/models/rating.rb3
-rw-r--r--activerecord/test/models/reference.rb2
-rw-r--r--activerecord/test/schema/schema.rb5
9 files changed, 86 insertions, 5 deletions
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
diff --git a/activerecord/test/fixtures/ratings.yml b/activerecord/test/fixtures/ratings.yml
new file mode 100644
index 0000000000..34e208efa3
--- /dev/null
+++ b/activerecord/test/fixtures/ratings.yml
@@ -0,0 +1,14 @@
+normal_comment_rating:
+ id: 1
+ comment_id: 8
+ value: 1
+
+special_comment_rating:
+ id: 2
+ comment_id: 6
+ value: 1
+
+sub_special_comment_rating:
+ id: 3
+ comment_id: 12
+ value: 1
diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb
index 88061b2145..1a3fb42b66 100644
--- a/activerecord/test/models/comment.rb
+++ b/activerecord/test/models/comment.rb
@@ -7,6 +7,7 @@ class Comment < ActiveRecord::Base
:conditions => { "posts.author_id" => 1 }
belongs_to :post, :counter_cache => true
+ has_many :ratings
def self.what_are_you
'a comment...'
diff --git a/activerecord/test/models/job.rb b/activerecord/test/models/job.rb
index 3333a02e27..46b1d87aa1 100644
--- a/activerecord/test/models/job.rb
+++ b/activerecord/test/models/job.rb
@@ -2,4 +2,6 @@ class Job < ActiveRecord::Base
has_many :references
has_many :people, :through => :references
belongs_to :ideal_reference, :class_name => 'Reference'
+
+ has_many :agents, :through => :people
end
diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb
index 951ec93c53..d35c51b660 100644
--- a/activerecord/test/models/person.rb
+++ b/activerecord/test/models/person.rb
@@ -13,6 +13,9 @@ class Person < ActiveRecord::Base
belongs_to :primary_contact, :class_name => 'Person'
has_many :agents, :class_name => 'Person', :foreign_key => 'primary_contact_id'
belongs_to :number1_fan, :class_name => 'Person'
+
+ has_many :agents_posts, :through => :agents, :source => :posts
+ has_many :agents_posts_authors, :through => :agents_posts, :source => :author
scope :males, :conditions => { :gender => 'M' }
scope :females, :conditions => { :gender => 'F' }
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index a3cb9c724a..f3b78c3647 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -46,6 +46,8 @@ class Post < ActiveRecord::Base
has_one :very_special_comment_with_post, :class_name => "VerySpecialComment", :include => :post
has_many :special_comments
has_many :nonexistant_comments, :class_name => 'Comment', :conditions => 'comments.id < 0'
+
+ has_many :special_comments_ratings, :through => :special_comments, :source => :ratings
has_and_belongs_to_many :categories
has_and_belongs_to_many :special_categories, :join_table => "categories_posts", :association_foreign_key => 'category_id'
diff --git a/activerecord/test/models/rating.rb b/activerecord/test/models/rating.rb
new file mode 100644
index 0000000000..12c4b5affa
--- /dev/null
+++ b/activerecord/test/models/rating.rb
@@ -0,0 +1,3 @@
+class Rating < ActiveRecord::Base
+ belongs_to :comment
+end
diff --git a/activerecord/test/models/reference.rb b/activerecord/test/models/reference.rb
index 4a17c936f5..2feb15d706 100644
--- a/activerecord/test/models/reference.rb
+++ b/activerecord/test/models/reference.rb
@@ -1,6 +1,8 @@
class Reference < ActiveRecord::Base
belongs_to :person
belongs_to :job
+
+ has_many :agents_posts_authors, :through => :person
end
class BadReference < ActiveRecord::Base
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index dbd5da45eb..2fa9a4521e 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -449,6 +449,11 @@ ActiveRecord::Schema.define do
t.string :type
end
+ create_table :ratings, :force => true do |t|
+ t.integer :comment_id
+ t.integer :value
+ end
+
create_table :readers, :force => true do |t|
t.integer :post_id, :null => false
t.integer :person_id, :null => false