aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/associations/through_association_scope.rb96
-rw-r--r--activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb8
-rw-r--r--activerecord/test/cases/associations/nested_has_many_through_associations_test.rb9
-rw-r--r--activerecord/test/fixtures/categories_posts.yml8
-rw-r--r--activerecord/test/models/author.rb8
5 files changed, 74 insertions, 55 deletions
diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb
index 09f92332cf..8c5b95439e 100644
--- a/activerecord/lib/active_record/associations/through_association_scope.rb
+++ b/activerecord/lib/active_record/associations/through_association_scope.rb
@@ -65,52 +65,56 @@ module ActiveRecord
@reflection.through_reflection_chain.each_cons(2) do |left, right|
polymorphic_join = nil
- case
- when left.source_reflection.nil?
- # TODO: Perhaps need to pay attention to left.options[:primary_key] and
- # left.options[:foreign_key] in places here
-
- case left.macro
- when :belongs_to
- left_primary_key = left.klass.primary_key
- right_primary_key = left.primary_key_name
- when :has_many, :has_one
- left_primary_key = left.primary_key_name
- right_primary_key = right.klass.primary_key
-
- if left.options[:as]
- polymorphic_join = "AND %s.%s = %s" % [
- table_aliases[left], "#{left.options[:as]}_type",
- # TODO: Why right.klass.name? Rather than left.active_record.name?
- # TODO: Also should maybe use the base_class (see related code in JoinAssociation)
- @owner.class.quote_value(right.klass.name)
- ]
- end
- when :has_and_belongs_to_many
- raise NotImplementedError
- end
- when left.source_reflection.macro == :belongs_to
- left_primary_key = left.klass.primary_key
- right_primary_key = left.source_reflection.primary_key_name
-
- if left.options[:source_type]
- polymorphic_join = "AND %s.%s = %s" % [
- table_aliases[right],
- left.source_reflection.options[:foreign_type].to_s,
- @owner.class.quote_value(left.options[:source_type])
- ]
- end
- else
- left_primary_key = left.source_reflection.primary_key_name
- right_primary_key = right.klass.primary_key
-
- if left.source_reflection.options[:as]
- polymorphic_join = "AND %s.%s = %s" % [
- table_aliases[left],
- "#{left.source_reflection.options[:as]}_type",
- @owner.class.quote_value(right.klass.name)
- ]
- end
+ if left.source_reflection.nil?
+ # TODO: Perhaps need to pay attention to left.options[:primary_key] and
+ # left.options[:foreign_key] in places here
+
+ case left.macro
+ when :belongs_to
+ left_primary_key = left.klass.primary_key
+ right_primary_key = left.primary_key_name
+ when :has_many, :has_one
+ left_primary_key = left.primary_key_name
+ right_primary_key = right.klass.primary_key
+
+ if left.options[:as]
+ polymorphic_join = "AND %s.%s = %s" % [
+ table_aliases[left], "#{left.options[:as]}_type",
+ # TODO: Why right.klass.name? Rather than left.active_record.name?
+ # TODO: Also should maybe use the base_class (see related code in JoinAssociation)
+ @owner.class.quote_value(right.klass.name)
+ ]
+ end
+ when :has_and_belongs_to_many
+ raise NotImplementedError
+ end
+ else
+ case left.source_reflection.macro
+ when :belongs_to
+ left_primary_key = left.klass.primary_key
+ right_primary_key = left.source_reflection.primary_key_name
+
+ if left.options[:source_type]
+ polymorphic_join = "AND %s.%s = %s" % [
+ table_aliases[right],
+ left.source_reflection.options[:foreign_type].to_s,
+ @owner.class.quote_value(left.options[:source_type])
+ ]
+ end
+ when :has_many, :has_one
+ left_primary_key = left.source_reflection.primary_key_name
+ right_primary_key = right.klass.primary_key
+
+ if left.source_reflection.options[:as]
+ polymorphic_join = "AND %s.%s = %s" % [
+ table_aliases[left],
+ "#{left.source_reflection.options[:as]}_type",
+ @owner.class.quote_value(right.klass.name)
+ ]
+ end
+ when :has_and_belongs_to_many
+ raise NotImplementedError
+ end
end
if right.quoted_table_name == table_aliases[right]
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
diff --git a/activerecord/test/fixtures/categories_posts.yml b/activerecord/test/fixtures/categories_posts.yml
index 9b67ab4fa4..3b41510cb1 100644
--- a/activerecord/test/fixtures/categories_posts.yml
+++ b/activerecord/test/fixtures/categories_posts.yml
@@ -21,3 +21,11 @@ sti_test_sti_habtm:
general_hello:
category_id: 1
post_id: 4
+
+general_misc_by_bob:
+ category_id: 1
+ post_id: 8
+
+technology_misc_by_bob:
+ category_id: 2
+ post_id: 8
diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb
index 1fbd729b60..584164f19a 100644
--- a/activerecord/test/models/author.rb
+++ b/activerecord/test/models/author.rb
@@ -83,9 +83,9 @@ class Author < ActiveRecord::Base
has_many :author_favorites
has_many :favorite_authors, :through => :author_favorites, :order => 'name'
- has_many :tagging, :through => :posts # through polymorphic has_one
- has_many :taggings, :through => :posts # through polymorphic has_many
- has_many :tags, :through => :posts # through has_many :through (on source reflection + polymorphic)
+ has_many :tagging, :through => :posts
+ has_many :taggings, :through => :posts
+ has_many :tags, :through => :posts
has_many :similar_posts, :through => :tags, :source => :tagged_posts
has_many :distinct_tags, :through => :posts, :source => :tags, :select => "DISTINCT tags.*", :order => "tags.name"
has_many :post_categories, :through => :posts, :source => :categories
@@ -100,6 +100,8 @@ class Author < ActiveRecord::Base
belongs_to :author_address, :dependent => :destroy
belongs_to :author_address_extra, :dependent => :delete, :class_name => "AuthorAddress"
+ has_many :post_categories, :through => :posts, :source => :categories
+
scope :relation_include_posts, includes(:posts)
scope :relation_include_tags, includes(:tags)