polyamorous 1.3.3 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/polyamorous.rb +13 -40
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +1 -9
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +2 -20
- data/lib/polyamorous/{activerecord_5.2_ruby_2 → activerecord_5.2.0_ruby_2}/join_association.rb +2 -10
- data/lib/polyamorous/{activerecord_5.2_ruby_2 → activerecord_5.2.0_ruby_2}/join_dependency.rb +3 -21
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb +12 -0
- data/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb +22 -0
- data/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb +81 -0
- data/lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb +2 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +2 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +81 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +2 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +2 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +2 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +2 -0
- data/lib/polyamorous/version.rb +1 -1
- data/polyamorous.gemspec +2 -4
- metadata +19 -49
- data/.gitignore +0 -6
- data/.travis.yml +0 -59
- data/Gemfile +0 -33
- data/LICENSE +0 -20
- data/README.md +0 -21
- data/Rakefile +0 -17
- data/lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_association.rb +0 -76
- data/lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_dependency.rb +0 -96
- data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_association.rb +0 -2
- data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_dependency.rb +0 -4
- data/lib/polyamorous/activerecord_4.1_ruby_2/join_association.rb +0 -2
- data/lib/polyamorous/activerecord_4.1_ruby_2/join_dependency.rb +0 -3
- data/lib/polyamorous/activerecord_4.1_ruby_2/make_polyamorous_inner_joins.rb +0 -14
- data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_association.rb +0 -46
- data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb +0 -87
- data/lib/polyamorous/activerecord_4.2_ruby_2/join_association.rb +0 -2
- data/lib/polyamorous/activerecord_4.2_ruby_2/join_dependency.rb +0 -24
- data/spec/blueprints/articles.rb +0 -5
- data/spec/blueprints/comments.rb +0 -5
- data/spec/blueprints/notes.rb +0 -3
- data/spec/blueprints/people.rb +0 -4
- data/spec/blueprints/tags.rb +0 -3
- data/spec/helpers/polyamorous_helper.rb +0 -26
- data/spec/polyamorous/join_association_spec.rb +0 -54
- data/spec/polyamorous/join_dependency_spec.rb +0 -102
- data/spec/polyamorous/join_spec.rb +0 -19
- data/spec/spec_helper.rb +0 -43
- data/spec/support/schema.rb +0 -98
@@ -1,14 +0,0 @@
|
|
1
|
-
module Polyamorous
|
2
|
-
module JoinDependencyExtensions
|
3
|
-
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
|
4
|
-
#
|
5
|
-
def make_polyamorous_inner_joins(parent, child)
|
6
|
-
make_constraints(
|
7
|
-
parent, child, child.tables, child.join_type || Arel::Nodes::InnerJoin
|
8
|
-
)
|
9
|
-
.concat child.children.flat_map { |c|
|
10
|
-
make_polyamorous_inner_joins(child, c)
|
11
|
-
}
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# active_record_4.2_ruby_1.9/join_association.rb
|
2
|
-
module Polyamorous
|
3
|
-
module JoinAssociationExtensions
|
4
|
-
include SwappingReflectionClass
|
5
|
-
def self.included(base)
|
6
|
-
base.class_eval do
|
7
|
-
attr_reader :join_type
|
8
|
-
alias_method_chain :initialize, :polymorphism
|
9
|
-
alias_method_chain :build_constraint, :polymorphism
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize_with_polymorphism(reflection, children,
|
14
|
-
polymorphic_class = nil, join_type = Arel::Nodes::InnerJoin)
|
15
|
-
@join_type = join_type
|
16
|
-
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
|
17
|
-
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
|
18
|
-
initialize_without_polymorphism(reflection, children)
|
19
|
-
self.reflection.options[:polymorphic] = true
|
20
|
-
end
|
21
|
-
else
|
22
|
-
initialize_without_polymorphism(reflection, children)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# Reference https://github.com/rails/rails/commit/9b15db51b78028bfecdb85595624de4b838adbd1
|
27
|
-
def ==(other)
|
28
|
-
base_klass == other.base_klass
|
29
|
-
end
|
30
|
-
|
31
|
-
def build_constraint_with_polymorphism(
|
32
|
-
klass, table, key, foreign_table, foreign_key
|
33
|
-
)
|
34
|
-
if reflection.polymorphic?
|
35
|
-
build_constraint_without_polymorphism(
|
36
|
-
klass, table, key, foreign_table, foreign_key
|
37
|
-
)
|
38
|
-
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
39
|
-
else
|
40
|
-
build_constraint_without_polymorphism(
|
41
|
-
klass, table, key, foreign_table, foreign_key
|
42
|
-
)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
# active_record_4.2_ruby_1.9/join_dependency.rb
|
2
|
-
require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
|
3
|
-
|
4
|
-
module Polyamorous
|
5
|
-
module JoinDependencyExtensions
|
6
|
-
def self.included(base)
|
7
|
-
base.extend ClassMethods
|
8
|
-
base.class_eval do
|
9
|
-
class << self
|
10
|
-
alias_method :walk_tree_without_polymorphism, :walk_tree
|
11
|
-
alias_method :walk_tree, :walk_tree_with_polymorphism
|
12
|
-
end
|
13
|
-
|
14
|
-
alias_method :build_without_polymorphism, :build
|
15
|
-
alias_method :build, :build_with_polymorphism
|
16
|
-
|
17
|
-
alias_method :join_constraints_without_polymorphism, :join_constraints
|
18
|
-
alias_method :join_constraints, :join_constraints_with_polymorphism
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Replaces ActiveRecord::Associations::JoinDependency#build
|
23
|
-
#
|
24
|
-
def build_with_polymorphism(associations, base_klass)
|
25
|
-
associations.map do |name, right|
|
26
|
-
if name.is_a? Join
|
27
|
-
reflection = find_reflection base_klass, name.name
|
28
|
-
reflection.check_validity!
|
29
|
-
klass = if reflection.polymorphic?
|
30
|
-
name.klass || base_klass
|
31
|
-
else
|
32
|
-
reflection.klass
|
33
|
-
end
|
34
|
-
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
35
|
-
else
|
36
|
-
reflection = find_reflection base_klass, name
|
37
|
-
reflection.check_validity!
|
38
|
-
if reflection.polymorphic?
|
39
|
-
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
40
|
-
end
|
41
|
-
JoinAssociation.new reflection, build(right, reflection.klass)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
47
|
-
# to call #make_polyamorous_inner_joins instead of #make_inner_joins
|
48
|
-
#
|
49
|
-
def join_constraints_with_polymorphism(outer_joins)
|
50
|
-
joins = join_root.children.flat_map { |child|
|
51
|
-
make_polyamorous_inner_joins join_root, child
|
52
|
-
}
|
53
|
-
joins.concat outer_joins.flat_map { |oj|
|
54
|
-
if join_root.match? oj.join_root
|
55
|
-
walk(join_root, oj.join_root)
|
56
|
-
else
|
57
|
-
oj.join_root.children.flat_map { |child|
|
58
|
-
make_outer_joins(oj.join_root, child)
|
59
|
-
}
|
60
|
-
end
|
61
|
-
}
|
62
|
-
end
|
63
|
-
|
64
|
-
module ClassMethods
|
65
|
-
# Replaces ActiveRecord::Associations::JoinDependency#self.walk_tree
|
66
|
-
#
|
67
|
-
def walk_tree_with_polymorphism(associations, hash)
|
68
|
-
case associations
|
69
|
-
when TreeNode
|
70
|
-
associations.add_to_tree(hash)
|
71
|
-
when Hash
|
72
|
-
associations.each do |k, v|
|
73
|
-
cache =
|
74
|
-
if TreeNode === k
|
75
|
-
k.add_to_tree(hash)
|
76
|
-
else
|
77
|
-
hash[k] ||= {}
|
78
|
-
end
|
79
|
-
walk_tree(v, cache)
|
80
|
-
end
|
81
|
-
else
|
82
|
-
walk_tree_without_polymorphism(associations, hash)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# active_record_4.2_ruby_2/join_dependency.rb
|
2
|
-
require 'polyamorous/activerecord_5.0_ruby_2/join_dependency'
|
3
|
-
|
4
|
-
module Polyamorous
|
5
|
-
module JoinDependencyExtensions
|
6
|
-
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
7
|
-
# to call #make_polyamorous_inner_joins instead of #make_inner_joins.
|
8
|
-
#
|
9
|
-
def join_constraints(outer_joins)
|
10
|
-
joins = join_root.children.flat_map { |child|
|
11
|
-
make_polyamorous_inner_joins join_root, child
|
12
|
-
}
|
13
|
-
joins.concat outer_joins.flat_map { |oj|
|
14
|
-
if join_root.match? oj.join_root
|
15
|
-
walk(join_root, oj.join_root)
|
16
|
-
else
|
17
|
-
oj.join_root.children.flat_map { |child|
|
18
|
-
make_outer_joins(oj.join_root, child)
|
19
|
-
}
|
20
|
-
end
|
21
|
-
}
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/spec/blueprints/articles.rb
DELETED
data/spec/blueprints/comments.rb
DELETED
data/spec/blueprints/notes.rb
DELETED
data/spec/blueprints/people.rb
DELETED
data/spec/blueprints/tags.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module PolyamorousHelper
|
2
|
-
if ActiveRecord::VERSION::STRING >= "4.1"
|
3
|
-
def new_join_association(reflection, children, klass)
|
4
|
-
Polyamorous::JoinAssociation.new reflection, children, klass
|
5
|
-
end
|
6
|
-
else
|
7
|
-
def new_join_association(reflection, join_dependency, parent, klass)
|
8
|
-
Polyamorous::JoinAssociation.new reflection, join_dependency, parent, klass
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
if ActiveRecord::VERSION::STRING >= "5.2"
|
13
|
-
def new_join_dependency(klass, associations = {})
|
14
|
-
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(klass.connection, klass.table_name, [])
|
15
|
-
Polyamorous::JoinDependency.new klass, klass.arel_table, associations, alias_tracker
|
16
|
-
end
|
17
|
-
else
|
18
|
-
def new_join_dependency(klass, associations = {})
|
19
|
-
Polyamorous::JoinDependency.new klass, associations, []
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def new_join(name, type = Polyamorous::InnerJoin, klass = nil)
|
24
|
-
Polyamorous::Join.new name, type, klass
|
25
|
-
end
|
26
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Polyamorous
|
4
|
-
describe JoinAssociation do
|
5
|
-
|
6
|
-
join_base, join_association_args, polymorphic =
|
7
|
-
if ActiveRecord::VERSION::STRING >= '4.1'
|
8
|
-
[:join_root, 'parent.children', 'reflection.options[:polymorphic]']
|
9
|
-
else
|
10
|
-
[:join_base, 'join_dependency, parent', 'options[:polymorphic]']
|
11
|
-
end
|
12
|
-
|
13
|
-
let(:join_dependency) { new_join_dependency Note, {} }
|
14
|
-
let(:reflection) { Note.reflect_on_association(:notable) }
|
15
|
-
let(:parent) { join_dependency.send(join_base) }
|
16
|
-
let(:join_association) {
|
17
|
-
eval("new_join_association(reflection, #{join_association_args}, Article)")
|
18
|
-
}
|
19
|
-
|
20
|
-
subject {
|
21
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
22
|
-
reflection, parent, Person
|
23
|
-
)
|
24
|
-
}
|
25
|
-
|
26
|
-
it 'respects polymorphism on equality test' do
|
27
|
-
expect(subject).to eq(
|
28
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
29
|
-
reflection, parent, Person
|
30
|
-
)
|
31
|
-
)
|
32
|
-
expect(subject).not_to eq(
|
33
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
34
|
-
reflection, parent, Article
|
35
|
-
)
|
36
|
-
)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'leaves the orginal reflection intact for thread safety' do
|
40
|
-
reflection.instance_variable_set(:@klass, Article)
|
41
|
-
join_association
|
42
|
-
.swapping_reflection_klass(reflection, Person) do |new_reflection|
|
43
|
-
expect(new_reflection.options).not_to equal reflection.options
|
44
|
-
expect(new_reflection.options).not_to have_key(:polymorphic)
|
45
|
-
expect(new_reflection.klass).to eq(Person)
|
46
|
-
expect(reflection.klass).to eq(Article)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'sets the polymorphic option to true after initializing' do
|
51
|
-
expect(join_association.instance_eval(polymorphic)).to be true
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Polyamorous
|
4
|
-
describe JoinDependency do
|
5
|
-
|
6
|
-
method, join_associations, join_base =
|
7
|
-
if ActiveRecord::VERSION::STRING >= '4.1'
|
8
|
-
[:instance_eval, 'join_root.drop(1)', :join_root]
|
9
|
-
else
|
10
|
-
[:send, 'join_associations', :join_base]
|
11
|
-
end
|
12
|
-
|
13
|
-
context 'with symbol joins' do
|
14
|
-
subject { new_join_dependency Person, articles: :comments }
|
15
|
-
|
16
|
-
specify { expect(subject.send(method, join_associations).size)
|
17
|
-
.to eq(2) }
|
18
|
-
specify { expect(subject.send(method, join_associations).map(&:join_type))
|
19
|
-
.to be_all { Polyamorous::InnerJoin } }
|
20
|
-
end
|
21
|
-
|
22
|
-
context 'with has_many :through association' do
|
23
|
-
subject { new_join_dependency Person, :authored_article_comments }
|
24
|
-
|
25
|
-
specify { expect(subject.send(method, join_associations).size)
|
26
|
-
.to eq 1 }
|
27
|
-
specify { expect(subject.send(method, join_associations).first.table_name)
|
28
|
-
.to eq 'comments' }
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'with outer join' do
|
32
|
-
subject { new_join_dependency Person, new_join(:articles, :outer) }
|
33
|
-
|
34
|
-
specify { expect(subject.send(method, join_associations).size)
|
35
|
-
.to eq 1 }
|
36
|
-
specify { expect(subject.send(method, join_associations).first.join_type)
|
37
|
-
.to eq Polyamorous::OuterJoin }
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'with nested outer joins' do
|
41
|
-
subject { new_join_dependency Person,
|
42
|
-
new_join(:articles, :outer) => new_join(:comments, :outer) }
|
43
|
-
|
44
|
-
specify { expect(subject.send(method, join_associations).size)
|
45
|
-
.to eq 2 }
|
46
|
-
specify { expect(subject.send(method, join_associations).map(&:join_type))
|
47
|
-
.to eq [Polyamorous::OuterJoin, Polyamorous::OuterJoin] }
|
48
|
-
specify { expect(subject.send(method, join_associations).map(&:join_type))
|
49
|
-
.to be_all { Polyamorous::OuterJoin } }
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'with polymorphic belongs_to join' do
|
53
|
-
subject { new_join_dependency Note, new_join(:notable, :inner, Person) }
|
54
|
-
|
55
|
-
specify { expect(subject.send(method, join_associations).size)
|
56
|
-
.to eq 1 }
|
57
|
-
specify { expect(subject.send(method, join_associations).first.join_type)
|
58
|
-
.to eq Polyamorous::InnerJoin }
|
59
|
-
specify { expect(subject.send(method, join_associations).first.table_name)
|
60
|
-
.to eq 'people' }
|
61
|
-
|
62
|
-
it 'finds a join association respecting polymorphism' do
|
63
|
-
parent = subject.send(join_base)
|
64
|
-
reflection = Note.reflect_on_association(:notable)
|
65
|
-
|
66
|
-
expect(subject.find_join_association_respecting_polymorphism(
|
67
|
-
reflection, parent, Person))
|
68
|
-
.to eq subject.send(method, join_associations).first
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'with polymorphic belongs_to join and nested symbol join' do
|
73
|
-
subject { new_join_dependency Note,
|
74
|
-
new_join(:notable, :inner, Person) => :comments }
|
75
|
-
|
76
|
-
specify { expect(subject.send(method, join_associations).size)
|
77
|
-
.to eq 2 }
|
78
|
-
specify { expect(subject.send(method, join_associations).map(&:join_type))
|
79
|
-
.to be_all { Polyamorous::InnerJoin } }
|
80
|
-
specify { expect(subject.send(method, join_associations).first.table_name)
|
81
|
-
.to eq 'people' }
|
82
|
-
specify { expect(subject.send(method, join_associations)[1].table_name)
|
83
|
-
.to eq 'comments' }
|
84
|
-
end
|
85
|
-
|
86
|
-
context '#left_outer_join in Rails 5 overrides join type specified',
|
87
|
-
if: ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR < 2 do
|
88
|
-
|
89
|
-
let(:join_type_class) do
|
90
|
-
new_join_dependency(
|
91
|
-
Person,
|
92
|
-
new_join(:articles)
|
93
|
-
).join_constraints(
|
94
|
-
[],
|
95
|
-
Arel::Nodes::OuterJoin
|
96
|
-
).first.joins.map(&:class)
|
97
|
-
end
|
98
|
-
|
99
|
-
specify { expect(join_type_class).to eq [Arel::Nodes::OuterJoin] }
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Polyamorous
|
4
|
-
describe Join do
|
5
|
-
it 'is a tree node' do
|
6
|
-
join = new_join(:articles, :outer)
|
7
|
-
expect(join).to be_kind_of(TreeNode)
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'can be added to a tree' do
|
11
|
-
join = new_join(:articles, :outer)
|
12
|
-
|
13
|
-
tree_hash = {}
|
14
|
-
join.add_to_tree(tree_hash)
|
15
|
-
|
16
|
-
expect(tree_hash[join]).to be {}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'machinist/active_record'
|
2
|
-
require 'sham'
|
3
|
-
require 'faker'
|
4
|
-
require 'polyamorous'
|
5
|
-
|
6
|
-
Time.zone = 'Eastern Time (US & Canada)'
|
7
|
-
|
8
|
-
Dir[File.expand_path('../{helpers,support,blueprints}/**/*.rb', __FILE__)]
|
9
|
-
.each do |f|
|
10
|
-
require f
|
11
|
-
end
|
12
|
-
|
13
|
-
Sham.define do
|
14
|
-
name { Faker::Name.name }
|
15
|
-
title { Faker::Lorem.sentence }
|
16
|
-
body { Faker::Lorem.paragraph }
|
17
|
-
salary { |index| 30000 + (index * 1000) }
|
18
|
-
tag_name { Faker::Lorem.words(3).join(' ') }
|
19
|
-
note { Faker::Lorem.words(7).join(' ') }
|
20
|
-
end
|
21
|
-
|
22
|
-
RSpec.configure do |config|
|
23
|
-
config.before(:suite) do
|
24
|
-
message = "Running Polyamorous specs with #{
|
25
|
-
ActiveRecord::Base.connection.adapter_name
|
26
|
-
}, Active Record #{::ActiveRecord::VERSION::STRING}, Arel #{Arel::VERSION
|
27
|
-
} and Ruby #{RUBY_VERSION}"
|
28
|
-
line = '=' * message.length
|
29
|
-
puts line, message, line
|
30
|
-
Schema.create
|
31
|
-
end
|
32
|
-
config.before(:all) { Sham.reset(:before_all) }
|
33
|
-
config.before(:each) { Sham.reset(:before_each) }
|
34
|
-
|
35
|
-
config.include PolyamorousHelper
|
36
|
-
end
|
37
|
-
|
38
|
-
RSpec::Matchers.define :be_like do |expected|
|
39
|
-
match do |actual|
|
40
|
-
actual.gsub(/^\s+|\s+$/, '').gsub(/\s+/, ' ').strip ==
|
41
|
-
expected.gsub(/^\s+|\s+$/, '').gsub(/\s+/, ' ').strip
|
42
|
-
end
|
43
|
-
end
|