From 8141318e93a2a833cfa673ee5dd0ea1ce68e50fa Mon Sep 17 00:00:00 2001 From: Greg Molnar Date: Tue, 12 Feb 2019 20:45:48 +0100 Subject: [PATCH] fix polymorphic joins with rails > 5.2 --- lib/ransack/adapters/active_record/context.rb | 6 +----- polyamorous/lib/polyamorous.rb | 5 +++++ .../activerecord_5.1_ruby_2/join_association.rb | 3 +-- .../activerecord_5.2.0_ruby_2/join_association.rb | 5 ++--- .../activerecord_5.2.0_ruby_2/join_dependency.rb | 1 - .../activerecord_5.2.0_ruby_2/reflection.rb | 12 ++++++++++++ .../activerecord_5.2.1_ruby_2/join_association.rb | 9 --------- .../activerecord_5.2.1_ruby_2/join_dependency.rb | 10 +++++++++- .../activerecord_5.2.1_ruby_2/reflection.rb | 2 ++ ransack.gemspec | 1 + spec/spec_helper.rb | 1 + 11 files changed, 34 insertions(+), 21 deletions(-) create mode 100644 polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb create mode 100644 polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb diff --git a/lib/ransack/adapters/active_record/context.rb b/lib/ransack/adapters/active_record/context.rb index 122c981..942aebb 100644 --- a/lib/ransack/adapters/active_record/context.rb +++ b/lib/ransack/adapters/active_record/context.rb @@ -326,7 +326,6 @@ module Ransack found_association = jd.instance_variable_get(:@join_root).children.last end - @associations_pot[found_association] = parent # TODO maybe we dont need to push associations here, we could loop @@ -337,14 +336,11 @@ module Ransack if ::ActiveRecord::VERSION::STRING > Constants::RAILS_5_2_0 @join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root)) else - @join_dependency.send( - :construct_tables!, jd.instance_variable_get(:@join_root), found_association - ) + @join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root), found_association) end # Leverage the stashed association functionality in AR @object = @object.joins(jd) - found_association end diff --git a/polyamorous/lib/polyamorous.rb b/polyamorous/lib/polyamorous.rb index f35a696..6c97dd7 100644 --- a/polyamorous/lib/polyamorous.rb +++ b/polyamorous/lib/polyamorous.rb @@ -19,6 +19,11 @@ if defined?(::ActiveRecord) require "polyamorous/activerecord_#{ar_version}_ruby_2/#{file}" end + if ar_version >= "5.2.0" + require "polyamorous/activerecord_#{ar_version}_ruby_2/reflection.rb" + ::ActiveRecord::Reflection::AbstractReflection.send(:prepend, Polyamorous::ReflectionExtensions) + end + Polyamorous::JoinDependency.send(:prepend, Polyamorous::JoinDependencyExtensions) Polyamorous::JoinDependency.singleton_class.send(:prepend, Polyamorous::JoinDependencyExtensions::ClassMethods) Polyamorous::JoinAssociation.send(:prepend, Polyamorous::JoinAssociationExtensions) diff --git a/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb b/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb index 9a0b1f3..7e9c24e 100644 --- a/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +++ b/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb @@ -7,8 +7,7 @@ module Polyamorous base.class_eval { attr_reader :join_type } end - def initialize(reflection, children, polymorphic_class = nil, - join_type = Arel::Nodes::InnerJoin) + def initialize(reflection, children, polymorphic_class = nil, join_type = Arel::Nodes::InnerJoin) @join_type = join_type if polymorphic_class && ::ActiveRecord::Base > polymorphic_class swapping_reflection_klass(reflection, polymorphic_class) do |reflection| diff --git a/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb b/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb index b9be34c..20cf2a4 100644 --- a/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +++ b/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb @@ -7,8 +7,7 @@ module Polyamorous base.class_eval { attr_reader :join_type } end - def initialize(reflection, children, alias_tracker, polymorphic_class = nil, - join_type = Arel::Nodes::InnerJoin) + def initialize(reflection, children, alias_tracker, polymorphic_class = nil, join_type = Arel::Nodes::InnerJoin) @join_type = join_type if polymorphic_class && ::ActiveRecord::Base > polymorphic_class swapping_reflection_klass(reflection, polymorphic_class) do |reflection| @@ -23,7 +22,7 @@ module Polyamorous def build_constraint(klass, table, key, foreign_table, foreign_key) if reflection.polymorphic? super(klass, table, key, foreign_table, foreign_key) - .and(foreign_table[reflection.foreign_type].eq(reflection.klass.name)) + .and(foreign_table[reflection.foreign_type].eq(reflection.klass.name)) else super(klass, table, key, foreign_table, foreign_key) end diff --git a/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb b/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb index 0603daf..2d840db 100644 --- a/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +++ b/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb @@ -38,7 +38,6 @@ module Polyamorous # passing an additional argument, `join_type`, to #join_constraints. # def join_constraints(outer_joins, join_type) - @alias_tracker = alias_tracker joins = join_root.children.flat_map { |child| if join_type == Arel::Nodes::OuterJoin make_polyamorous_left_outer_joins join_root, child diff --git a/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb b/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb new file mode 100644 index 0000000..b9b8c32 --- /dev/null +++ b/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb @@ -0,0 +1,12 @@ +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) + end + end + end +end diff --git a/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb b/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb index 97f7068..8b39760 100644 --- a/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb +++ b/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb @@ -18,14 +18,5 @@ module Polyamorous super(reflection, children) end end - - def build_constraint(klass, table, key, foreign_table, foreign_key) - if reflection.polymorphic? - super(klass, table, key, foreign_table, foreign_key) - .and(foreign_table[reflection.foreign_type].eq(reflection.klass.name)) - else - super(klass, table, key, foreign_table, foreign_key) - end - end end end diff --git a/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb b/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb index edbd257..41d3b5b 100644 --- a/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb +++ b/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb @@ -3,7 +3,6 @@ module Polyamorous module JoinDependencyExtensions # Replaces ActiveRecord::Associations::JoinDependency#build - # def build(associations, base_klass) associations.map do |name, right| if name.is_a? Join @@ -30,6 +29,15 @@ module Polyamorous end end + private + def make_constraints(parent, child, join_type = Arel::Nodes::OuterJoin) + foreign_table = parent.table + foreign_klass = parent.base_klass + join_type = child.join_type || join_type if join_type == Arel::Nodes::InnerJoin + joins = child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker) + joins.concat child.children.flat_map { |c| make_constraints(child, c, join_type) } + end + module ClassMethods # Prepended before ActiveRecord::Associations::JoinDependency#walk_tree # diff --git a/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb b/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb new file mode 100644 index 0000000..e66bf90 --- /dev/null +++ b/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb @@ -0,0 +1,2 @@ +# active_record_5.2.1_ruby_2/reflection.rb +require 'polyamorous/activerecord_5.2.0_ruby_2/reflection' diff --git a/ransack.gemspec b/ransack.gemspec index 9d2e4d6..6eb29c0 100644 --- a/ransack.gemspec +++ b/ransack.gemspec @@ -28,6 +28,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'pg', '~> 0.21' s.add_development_dependency 'mysql2', '0.3.20' s.add_development_dependency 'pry', '0.10' + s.add_development_dependency 'byebug' s.files = `git ls-files`.split("\n") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e1f57c1..f9c5d78 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,6 +4,7 @@ require 'faker' require 'ransack' require 'pry' require 'simplecov' +require 'byebug' SimpleCov.start I18n.enforce_available_locales = false