Skip to content
This repository has been archived by the owner on Nov 12, 2019. It is now read-only.

Commit

Permalink
Merge pull request #28 from gssbzn/add-rails-5-2
Browse files Browse the repository at this point in the history
Add support to rails 5.2
  • Loading branch information
scarroll32 authored Dec 29, 2017
2 parents f89f2a2 + 577e79a commit d34bcc1
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 24 deletions.
5 changes: 0 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ matrix:
- rvm: 2.2.8
env: RAILS=master DB=postgres

allow_failures:
- env: RAILS=master DB=sqlite3
- env: RAILS=master DB=mysql
- env: RAILS=master DB=postgres

before_script:
- mysql -e 'create database ransack collate utf8_general_ci;'
- mysql -e 'use ransack;show variables like "%character%";show variables like "%collation%";'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# active_record_5.0_ruby_2/join_association.rb
require 'polyamorous/activerecord_5.1_ruby_2/join_association'
require 'polyamorous/activerecord_5.1_ruby_2/join_association'
2 changes: 1 addition & 1 deletion lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# active_record_5.0_ruby_2/join_dependency.rb
require 'polyamorous/activerecord_5.1_ruby_2/join_dependency'
require 'polyamorous/activerecord_5.1_ruby_2/join_dependency'
4 changes: 2 additions & 2 deletions lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def self.prepended(base)
end

def initialize(reflection, children, polymorphic_class = nil,
join_type = Arel::Nodes::InnerJoin)
join_type = Arel::Nodes::InnerJoin)
@join_type = join_type
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
Expand All @@ -30,7 +30,7 @@ def ==(other)
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
Expand Down
8 changes: 4 additions & 4 deletions lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ def build(associations, base_klass)
reflection.check_eager_loadable! if ActiveRecord::VERSION::MAJOR >= 5

klass = if reflection.polymorphic?
name.klass || base_klass
else
reflection.klass
end
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
Expand Down
39 changes: 39 additions & 0 deletions lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# active_record_5.2_ruby_2/join_association.rb

module Polyamorous
module JoinAssociationExtensions
include SwappingReflectionClass
def self.prepended(base)
base.class_eval { attr_reader :join_type }
end

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|
super(reflection, children, alias_tracker)
self.reflection.options[:polymorphic] = true
end
else
super(reflection, children, alias_tracker)
end
end

# Reference: https://github.com/rails/rails/commit/9b15db5
# NOTE: Not sure we still need it?
#
def ==(other)
base_klass == other.base_klass
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
130 changes: 130 additions & 0 deletions lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# active_record_5.2_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! if ActiveRecord::VERSION::MAJOR >= 5

klass = if reflection.polymorphic?
name.klass || base_klass
else
reflection.klass
end
JoinAssociation.new(reflection, build(right, klass), alias_tracker, name.klass, name.type)
else
reflection = find_reflection base_klass, name
reflection.check_validity!
reflection.check_eager_loadable! if ActiveRecord::VERSION::MAJOR >= 5

if reflection.polymorphic?
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
end
JoinAssociation.new(reflection, build(right, reflection.klass), alias_tracker)
end
end
end

def find_join_association_respecting_polymorphism(reflection, parent, klass)
if association = parent.children.find { |j| j.reflection == reflection }
unless reflection.polymorphic?
association
else
association if association.base_klass == klass
end
end
end

def build_join_association_respecting_polymorphism(reflection, parent, klass)
if reflection.polymorphic? && klass
JoinAssociation.new(reflection, self, alias_tracker, klass)
else
JoinAssociation.new(reflection, self, alias_tracker)
end
end

# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
#
# This internal method was changed in Rails 5.0 by commit
# https://github.com/rails/rails/commit/e038975 which added
# left_outer_joins (see #make_polyamorous_left_outer_joins below) and added
# passing an additional argument, `join_type`, to #join_constraints.
#
def join_constraints(outer_joins, join_type)
joins = join_root.children.flat_map { |child|
if join_type == Arel::Nodes::OuterJoin
make_polyamorous_left_outer_joins join_root, child
else
make_polyamorous_inner_joins join_root, child
end
}

joins.concat outer_joins.flat_map { |oj|
if join_root.match? oj.join_root
walk(join_root, oj.join_root)
else
oj.join_root.children.flat_map { |child|
make_outer_joins(oj.join_root, child)
}
end
}
end

# Replaces ActiveRecord::Associations::JoinDependency#make_left_outer_joins,
# a new method that was added in Rails 5.0 with the following commit:
# https://github.com/rails/rails/commit/e038975
#
def make_polyamorous_left_outer_joins(parent, child)
tables = child.tables
join_type = Arel::Nodes::OuterJoin
info = make_constraints parent, child, tables, join_type

[info] + child.children.flat_map { |c|
make_polyamorous_left_outer_joins(child, c)
}
end

# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
#
def make_polyamorous_inner_joins(parent, child)
tables = child.tables
join_type = child.join_type || Arel::Nodes::InnerJoin
info = make_constraints parent, child, tables, join_type

[info] + child.children.flat_map { |c|
make_polyamorous_inner_joins(child, c)
}
end

private :make_polyamorous_inner_joins, :make_polyamorous_left_outer_joins

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
12 changes: 9 additions & 3 deletions spec/helpers/polyamorous_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ def new_join_association(reflection, join_dependency, parent, klass)
end
end

def new_join_dependency(klass, associations = {})
Polyamorous::JoinDependency.new klass, associations, []
if ActiveRecord::VERSION::STRING >= "5.2"
def new_join_dependency(klass, associations = {})
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(klass.connection, klass.table_name, [])
Polyamorous::JoinDependency.new klass, klass.arel_table, associations, alias_tracker
end
else
def new_join_dependency(klass, associations = {})
Polyamorous::JoinDependency.new klass, associations, []
end
end

def new_join(name, type = Polyamorous::InnerJoin, klass = nil)
Polyamorous::Join.new name, type, klass
end

end
21 changes: 13 additions & 8 deletions spec/polyamorous/join_dependency_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ module Polyamorous
end

context 'with symbol joins' do
subject { new_join_dependency Person, :articles => :comments }
subject { new_join_dependency Person, articles: :comments }

specify { expect(subject.send(method, join_associations).size)
.to eq 2 }
.to eq(2) }
specify { expect(subject.send(method, join_associations).map(&:join_type))
.to be_all { Polyamorous::InnerJoin } }
end
Expand Down Expand Up @@ -84,12 +84,17 @@ module Polyamorous
end

context '#left_outer_join in Rails 5 overrides join type specified',
if: ActiveRecord::VERSION::MAJOR >= 5 do

let(:join_type_class) {
new_join_dependency(Person, new_join(:articles))
.join_constraints([], Arel::Nodes::OuterJoin).first.joins.map(&:class)
}
if: ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR < 2 do

let(:join_type_class) do
new_join_dependency(
Person,
new_join(:articles)
).join_constraints(
[],
Arel::Nodes::OuterJoin
).first.joins.map(&:class)
end

specify { expect(join_type_class).to eq [Arel::Nodes::OuterJoin] }
end
Expand Down

0 comments on commit d34bcc1

Please sign in to comment.