From db3ff259ea7c9b4c3660c0476e847907f90b762e Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sun, 11 Jun 2017 20:13:21 +0900 Subject: Fix eager loading association with scope including joins Fixes #28324. --- .../associations/join_dependency/join_association.rb | 14 ++++++++++---- activerecord/lib/active_record/reflection.rb | 18 +++++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'activerecord/lib') 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 d0c1848079..b14ddfeeeb 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_association.rb @@ -34,13 +34,19 @@ module ActiveRecord table = tables.shift klass = reflection.klass - join_scope = reflection.join_scope(table, foreign_table, foreign_klass) - - binds.concat join_scope.bound_attributes - constraint = join_scope.arel.constraints + constraint = reflection.build_join_constraint(table, foreign_table) joins << table.create_join(table, table.create_on(constraint), join_type) + join_scope = reflection.join_scope(table, foreign_klass) + + if join_scope.arel.constraints.any? + binds.concat join_scope.bound_attributes + joins.concat join_scope.arel.join_sources + right = joins.last.right + right.expr = right.expr.and(join_scope.arel.constraints) + end + # The current table in this iteration becomes the foreign table in the next foreign_table, foreign_klass = table, klass end diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 8ff2f50fdb..a453ca55c7 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -185,19 +185,23 @@ module ActiveRecord end deprecate :scope_chain - def join_scope(table, foreign_table, foreign_klass) - predicate_builder = predicate_builder(table) - scope_chain_items = join_scopes(table, predicate_builder) - klass_scope = klass_join_scope(table, predicate_builder) - + def build_join_constraint(table, foreign_table) key = join_keys.key foreign_key = join_keys.foreign_key - klass_scope.where!(table[key].eq(foreign_table[foreign_key])) + constraint = table[key].eq(foreign_table[foreign_key]) if klass.finder_needs_type_condition? - klass_scope.where!(klass.send(:type_condition, table)) + table.create_and([constraint, klass.send(:type_condition, table)]) + else + constraint end + end + + def join_scope(table, foreign_klass) + predicate_builder = predicate_builder(table) + scope_chain_items = join_scopes(table, predicate_builder) + klass_scope = klass_join_scope(table, predicate_builder) if type klass_scope.where!(type => foreign_klass.base_class.sti_name) -- cgit v1.2.3