Skip to content

Instantly share code, notes, and snippets.

@AquaGeek
Created May 14, 2011 02:35
Show Gist options
  • Select an option

  • Save AquaGeek/971834 to your computer and use it in GitHub Desktop.

Select an option

Save AquaGeek/971834 to your computer and use it in GitHub Desktop.
Rails Lighthouse ticket #6685
From 0b5a91673ee74ca6e1acbbfd53362a05de0b5907 Mon Sep 17 00:00:00 2001
From: Ryan Aipperspach <ryan@goodguide.com>
Date: Thu, 7 Apr 2011 13:39:12 -0700
Subject: [PATCH] Put conditions for polymorphic joins in the ON instead of WHERE clause, in order to support OUTER JOINs
---
.../associations/association_scope.rb | 4 +++-
.../join_dependency/join_association.rb | 1 +
.../lib/active_record/associations/join_helper.rb | 15 +++++++++++++++
activerecord/lib/active_record/reflection.rb | 4 ----
.../test/cases/associations/join_model_test.rb | 15 +++++++++++++++
5 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb
index ab102b2..8fdb92b 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -87,7 +87,9 @@ module ActiveRecord
end
else
constraint = table[key].eq(foreign_table[foreign_key])
- join = join(foreign_table, constraint)
+ constraint = append_source_type_condition(constraint, table, foreign_table, reflection)
+
+ join = join(foreign_table, constraint)
scope = scope.joins(join)
diff --git a/activerecord/lib/active_record/associations/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/join_dependency/join_association.rb
index 4121a5b..f44efb2 100644
--- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb
+++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb
@@ -90,6 +90,7 @@ module ActiveRecord
end
constraint = table[key].eq(foreign_table[foreign_key])
+ constraint = append_source_type_condition(constraint, table, foreign_table, reflection)
if reflection.klass.finder_needs_type_condition?
constraint = table.create_and([
diff --git a/activerecord/lib/active_record/associations/join_helper.rb b/activerecord/lib/active_record/associations/join_helper.rb
index eae546e..9f56b5a 100644
--- a/activerecord/lib/active_record/associations/join_helper.rb
+++ b/activerecord/lib/active_record/associations/join_helper.rb
@@ -26,6 +26,21 @@ module ActiveRecord
end
tables
end
+
+ def append_source_type_condition(constraint, table, foreign_table, reflection)
+ source_type = reflection.options[:source_type] ||
+ (reflection.source_reflection &&
+ reflection.source_reflection.options[:source_type])
+
+ if (source_type)
+ table.create_and([
+ constraint,
+ foreign_table[reflection.foreign_type].eq(source_type)
+ ])
+ else
+ constraint
+ end
+ end
def table_name_for(reflection)
reflection.table_name
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index e801bc4..339ceae 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -450,10 +450,6 @@ module ActiveRecord
through_conditions = through_reflection.conditions
- if options[:source_type]
- through_conditions.first << { foreign_type => options[:source_type] }
- end
-
# Recursively fill out the rest of the array from the through reflection
conditions += through_conditions
diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb
index 5a7b139..d01544d 100644
--- a/activerecord/test/cases/associations/join_model_test.rb
+++ b/activerecord/test/cases/associations/join_model_test.rb
@@ -362,6 +362,21 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
end
assert_equal 5, tag_with_include.taggings.length
end
+
+ def test_has_many_polymporphic_with_source_type_and_some_empty_children
+ tags(:misc).taggings.destroy_all
+ tags(:blue).taggings.destroy_all
+
+ assert tags(:general).taggings.present?
+ assert tags(:misc).taggings.empty?
+ assert tags(:blue).taggings.empty?
+
+ tags_without_taggings = Tag.includes(:tagged_posts).where(:taggings => {:id => nil}).limit(100).all
+
+ desired = tags(:misc, :blue)
+
+ assert_equal desired.sort_by(&:id), tags_without_taggings.sort_by(&:id)
+ end
def test_has_many_through_has_many_find_all
assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first
--
1.6.5.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment