aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2019-05-02 21:42:56 +0900
committerRyuta Kamizono <kamipo@gmail.com>2019-05-15 22:00:01 +0900
commitec6dfdc8d21031e07dd381853ff37fcc63f8bd86 (patch)
tree0dbef488d2355d349279f0ae22588d92b74deeb3
parent4511d4bf7c931fd88b9f2aa8488cf3cf762639f7 (diff)
downloadrails-ec6dfdc8d21031e07dd381853ff37fcc63f8bd86.tar.gz
rails-ec6dfdc8d21031e07dd381853ff37fcc63f8bd86.tar.bz2
rails-ec6dfdc8d21031e07dd381853ff37fcc63f8bd86.zip
Fix eager loading associations with string joins not to raise NoMethodError
Fixes #34456.
-rw-r--r--activerecord/lib/active_record/associations/join_dependency/join_association.rb13
-rw-r--r--activerecord/test/cases/associations/eager_test.rb11
-rw-r--r--activerecord/test/models/rating.rb1
3 files changed, 23 insertions, 2 deletions
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 ca0305abbb..6a7e92dc28 100644
--- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb
+++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb
@@ -44,8 +44,7 @@ module ActiveRecord
unless others.empty?
joins.concat arel.join_sources
- right = joins.last.right
- right.expr.children.concat(others)
+ append_constraints(joins.last, others)
end
# The current table in this iteration becomes the foreign table in the next
@@ -65,6 +64,16 @@ module ActiveRecord
@readonly = reflection.scope && reflection.scope_for(base_klass.unscoped).readonly_value
end
+
+ private
+ def append_constraints(join, constraints)
+ if join.is_a?(Arel::Nodes::StringJoin)
+ join_string = table.create_and(constraints.unshift(join.left))
+ join.left = Arel.sql(base_klass.connection.visitor.compile(join_string))
+ else
+ join.right.expr.children.concat(constraints)
+ end
+ end
end
end
end
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 49bcb1d010..9ed25ca7c2 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -101,6 +101,17 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal [taggings(:normal_comment_rating)], rating.taggings_without_tag
end
+ def test_loading_association_with_string_joins
+ rating = Rating.first
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_with_no_tag
+
+ rating = Rating.preload(:taggings_with_no_tag).first
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_with_no_tag
+
+ rating = Rating.eager_load(:taggings_with_no_tag).first
+ assert_equal [taggings(:normal_comment_rating)], rating.taggings_with_no_tag
+ end
+
def test_loading_with_scope_including_joins
member = Member.first
assert_equal members(:groucho), member
diff --git a/activerecord/test/models/rating.rb b/activerecord/test/models/rating.rb
index 49aa38285f..2a18ea45ac 100644
--- a/activerecord/test/models/rating.rb
+++ b/activerecord/test/models/rating.rb
@@ -4,4 +4,5 @@ class Rating < ActiveRecord::Base
belongs_to :comment
has_many :taggings, as: :taggable
has_many :taggings_without_tag, -> { left_joins(:tag).where("tags.id": nil) }, as: :taggable, class_name: "Tagging"
+ has_many :taggings_with_no_tag, -> { joins("LEFT OUTER JOIN tags ON tags.id = taggings.tag_id").where("tags.id": nil) }, as: :taggable, class_name: "Tagging"
end