diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index f35a40fb2f09b..8b5c6f6ec2c9b 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -70,6 +70,10 @@ def initialize(base, table, associations, join_type) @join_type = join_type end + def base_klass + join_root.base_klass + end + def reflections join_root.drop(1).map!(&:reflection) end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 153056c0738cd..b826f29d09b3d 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1108,6 +1108,10 @@ def build_joins(manager, joins, aliases) buckets[:stashed_join] << construct_join_dependency(left_joins, Arel::Nodes::OuterJoin) end + if joins.last.is_a?(ActiveRecord::Associations::JoinDependency) + buckets[:stashed_join] << joins.pop if joins.last.base_klass == klass + end + joins.map! do |join| if join.is_a?(String) table.create_string_join(Arel.sql(join.strip)) unless join.blank? diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index 166a59ec7b271..1ec349aa73487 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -79,6 +79,14 @@ def test_deduplicate_joins assert_equal [authors(:david)], authors end + def test_eager_load_with_string_joins + string_join = <<~SQL + LEFT JOIN people agents_people ON agents_people.primary_contact_id = agents_people_2.id AND agents_people.id > agents_people_2.id + SQL + + assert_equal 3, Person.eager_load(:agents).joins(string_join).count + end + def test_construct_finder_sql_ignores_empty_joins_hash sql = Author.joins({}).to_sql assert_no_match(/JOIN/i, sql)