From d7ebea0f7ff1df27d8f4171343074cd439b42df2 Mon Sep 17 00:00:00 2001 From: Vassilis Rodokanakis Date: Tue, 28 May 2019 11:55:16 +0300 Subject: [PATCH] Add support for Rails 6 in polyamorous --- polyamorous/lib/polyamorous.rb | 4 +- .../join_association.rb | 2 + .../join_dependency.rb | 81 +++++++++++++++++++ .../activerecord_6.0_ruby_2/reflection.rb | 2 + 4 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb create mode 100644 polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb create mode 100644 polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb diff --git a/polyamorous/lib/polyamorous.rb b/polyamorous/lib/polyamorous.rb index 6c97dd7..3137df5 100644 --- a/polyamorous/lib/polyamorous.rb +++ b/polyamorous/lib/polyamorous.rb @@ -12,8 +12,8 @@ if defined?(::ActiveRecord) require 'polyamorous/swapping_reflection_class' ar_version = ::ActiveRecord::VERSION::STRING[0,3] - ar_version = ::ActiveRecord::VERSION::STRING[0,5] if ar_version >= "5.2" - ar_version = "5.2.1" if ::ActiveRecord::VERSION::STRING >= "5.2.1" + ar_version = ::ActiveRecord::VERSION::STRING[0,5] if ar_version >= "5.2" && ::ActiveRecord::VERSION::STRING < "6.0" + ar_version = "5.2.1" if ::ActiveRecord::VERSION::STRING >= "5.2.1" && ::ActiveRecord::VERSION::STRING < "6.0" %w(join_association join_dependency).each do |file| require "polyamorous/activerecord_#{ar_version}_ruby_2/#{file}" diff --git a/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb b/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb new file mode 100644 index 0000000..ea2b61e --- /dev/null +++ b/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb @@ -0,0 +1,2 @@ +# active_record_6.0_ruby_2/join_association +require 'polyamorous/activerecord_5.2.1_ruby_2/join_association' diff --git a/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb b/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb new file mode 100644 index 0000000..bbe00a8 --- /dev/null +++ b/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb @@ -0,0 +1,81 @@ +# active_record_6.0_ruby_2/join_dependency.rb + +module Polyamorous + module JoinDependencyExtensions + # Replaces ActiveRecord::Associations::JoinDependency#build + def build(associations, base_klass) + associations.map do |name, right| + if name.is_a? Join + reflection = find_reflection base_klass, name.name + reflection.check_validity! + reflection.check_eager_loadable! + + klass = if reflection.polymorphic? + name.klass || base_klass + else + reflection.klass + end + JoinAssociation.new(reflection, build(right, klass), name.klass, name.type) + else + reflection = find_reflection base_klass, name + reflection.check_validity! + reflection.check_eager_loadable! + + if reflection.polymorphic? + raise ActiveRecord::EagerLoadPolymorphicError.new(reflection) + end + JoinAssociation.new(reflection, build(right, reflection.klass)) + end + end + end + + def join_constraints(joins_to_add, alias_tracker) + @alias_tracker = alias_tracker + + construct_tables!(join_root) + joins = make_join_constraints(join_root, join_type) + + joins.concat joins_to_add.flat_map { |oj| + construct_tables!(oj.join_root) + if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name + walk join_root, oj.join_root, oj.join_type + else + make_join_constraints(oj.join_root, oj.join_type) + 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 + # + def walk_tree(associations, hash) + case associations + when TreeNode + associations.add_to_tree(hash) + when Hash + associations.each do |k, v| + cache = + if TreeNode === k + k.add_to_tree(hash) + else + hash[k] ||= {} + end + walk_tree(v, cache) + end + else + super(associations, hash) + end + end + end + + end +end diff --git a/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb b/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb new file mode 100644 index 0000000..0417c10 --- /dev/null +++ b/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb @@ -0,0 +1,2 @@ +# active_record_6.0_ruby_2/reflection.rb +require 'polyamorous/activerecord_5.2.0_ruby_2/reflection'