diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2017-06-11 20:13:21 +0900 |
---|---|---|
committer | Ryuta Kamizono <kamipo@gmail.com> | 2017-07-04 08:00:28 +0900 |
commit | db3ff259ea7c9b4c3660c0476e847907f90b762e (patch) | |
tree | 847afb82d1f50189a00fbb1e7b93003aeaafcd31 | |
parent | 2bfa2c02a891d4817832807343c6f1d56e9bae50 (diff) | |
download | rails-db3ff259ea7c9b4c3660c0476e847907f90b762e.tar.gz rails-db3ff259ea7c9b4c3660c0476e847907f90b762e.tar.bz2 rails-db3ff259ea7c9b4c3660c0476e847907f90b762e.zip |
Fix eager loading association with scope including joins
Fixes #28324.
4 files changed, 28 insertions, 11 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 7404c1bd8f..8d900d9669 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* Fix eager loading/preloading association with scope including joins. + + Fixes #28324. + + *Ryuta Kamizono* + * Fix transactions to apply state to child transactions Previously if you had a nested transaction and the outer transaction was rolledback the record from the 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) diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index db8248dd99..c0bab19e82 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -70,6 +70,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_loading_with_scope_including_joins assert_equal clubs(:boring_club), Member.preload(:general_club).find(1).general_club + assert_equal clubs(:boring_club), Member.eager_load(:general_club).find(1).general_club end def test_with_ordering |