From 01d35efdce5dd0e75f420a26b5950d3351ef18f3 Mon Sep 17 00:00:00 2001 From: Phil Coggins Date: Mon, 11 May 2020 13:44:21 -0600 Subject: [PATCH] Fixes polymorphic joins. * Polymorphic joins have been missing a critical join constraint that is responsible for only returning polymorphic records of the specified type. * Override ActiveRecord::Reflection::AbstractReflection#join_scope to add this constraint if the reflection is polymorphic. --- .../activerecord_5.2_ruby_2/reflection.rb | 21 +++++++++++++------ spec/ransack/search_spec.rb | 4 ++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb b/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb index b9b8c32ae..9e0bfb678 100644 --- a/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +++ b/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb @@ -1,11 +1,20 @@ module Polyamorous module ReflectionExtensions - def build_join_constraint(table, foreign_table) - if polymorphic? - super(table, foreign_table) - .and(foreign_table[foreign_type].eq(klass.name)) - else - super(table, foreign_table) + if ActiveRecord.version > ::Gem::Version.new('5.2.3') + def join_scope(table, foreign_table, foreign_klass) + if respond_to?(:polymorphic?) && polymorphic? + super.where!(foreign_table[foreign_type].eq(klass.name)) + else + super + end + end + else + def build_join_constraint(table, foreign_table) + if polymorphic? + super.and(foreign_table[foreign_type].eq(klass.name)) + else + super + end end end end diff --git a/spec/ransack/search_spec.rb b/spec/ransack/search_spec.rb index be4141643..3ac6a9c7a 100644 --- a/spec/ransack/search_spec.rb +++ b/spec/ransack/search_spec.rb @@ -257,6 +257,9 @@ module Ransack let(:children_people_name_field) { "#{quote_table_name("children_people")}.#{quote_column_name("name")}" } + let(:notable_type_field) { + "#{quote_table_name("notes")}.#{quote_column_name("notable_type")}" + } it 'evaluates conditions contextually' do s = Search.new(Person, children_name_eq: 'Ernie') expect(s.result).to be_an ActiveRecord::Relation @@ -328,6 +331,7 @@ module Ransack s = Search.new(Note, notable_of_Person_type_name_eq: 'Ernie').result expect(s).to be_an ActiveRecord::Relation expect(s.to_sql).to match /#{people_name_field} = 'Ernie'/ + expect(s.to_sql).to match /#{notable_type_field} = 'Person'/ end it 'evaluates nested conditions' do