polyamorous 1.2.0 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +34 -30
- data/README.md +13 -10
- data/lib/polyamorous/activerecord_4.1_ruby_1.9/join_dependency.rb +1 -1
- data/lib/polyamorous/activerecord_4.1_ruby_2/join_association.rb +1 -1
- data/lib/polyamorous/activerecord_4.1_ruby_2/join_dependency.rb +1 -1
- data/lib/polyamorous/activerecord_4.1_ruby_2/{make_joins.rb → make_polyamorous_inner_joins.rb} +5 -2
- data/lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb +16 -23
- data/lib/polyamorous/activerecord_4.2_ruby_2/join_association.rb +1 -36
- data/lib/polyamorous/activerecord_4.2_ruby_2/join_dependency.rb +5 -86
- data/lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb +2 -0
- data/lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb +2 -0
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +39 -0
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +130 -0
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +39 -0
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +130 -0
- data/lib/polyamorous/version.rb +1 -1
- data/lib/polyamorous.rb +2 -9
- data/polyamorous.gemspec +2 -2
- data/spec/helpers/polyamorous_helper.rb +9 -3
- data/spec/polyamorous/join_association_spec.rb +47 -4
- data/spec/polyamorous/join_dependency_spec.rb +95 -4
- data/spec/polyamorous/join_spec.rb +1 -1
- metadata +14 -16
- data/spec/support/shared_examples/join_association_3_and_4.0.rb +0 -42
- data/spec/support/shared_examples/join_association_4.1.rb +0 -42
- data/spec/support/shared_examples/join_dependency_3_and_4.0.rb +0 -65
- data/spec/support/shared_examples/join_dependency_4.1.rb +0 -65
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c99b340d1137da69048738077239bf10471388fe
|
|
4
|
+
data.tar.gz: 289568abe8acfc3dd93b8c3fb45f7a6910fd1752
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0f035d8d3d7ec83992e5eb63f2bd608a7131c1104ad86b5320d7eb953d7e6f8159bf4458636cb03ca0506e18c1bba83f996ede2772bbd11671eec38b251314b0
|
|
7
|
+
data.tar.gz: 7186a137a3299ce00fdf66526e5a71763cbd99737811e48f0285b2dd2ea1b1bc0952fbf1cb750c24e26393708071e3f753a794022261871e88d1a6958edd0fe6
|
data/.travis.yml
CHANGED
|
@@ -1,53 +1,57 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
|
|
3
3
|
sudo: false
|
|
4
|
+
cache: bundler
|
|
4
5
|
|
|
5
6
|
before_install:
|
|
6
7
|
- travis_retry gem install bundler
|
|
7
8
|
|
|
8
9
|
rvm:
|
|
9
|
-
- 2.
|
|
10
|
-
- 2.
|
|
11
|
-
- 2.
|
|
12
|
-
-
|
|
10
|
+
- 2.5.0
|
|
11
|
+
- 2.4.3
|
|
12
|
+
- 2.3.6
|
|
13
|
+
- 2.2.9
|
|
13
14
|
|
|
14
15
|
env:
|
|
15
16
|
- RAILS=4-2-stable AREL=6-0-stable DB=sqlite
|
|
16
17
|
- RAILS=4-2-stable AREL=6-0-stable DB=mysql
|
|
17
18
|
- RAILS=4-2-stable AREL=6-0-stable DB=postgres
|
|
19
|
+
- RAILS=5-0-stable AREL=7-0-stable DB=sqlite
|
|
20
|
+
- RAILS=5-0-stable AREL=7-0-stable DB=mysql
|
|
21
|
+
- RAILS=5-0-stable AREL=7-0-stable DB=postgres
|
|
22
|
+
- RAILS=5-1-stable AREL=8-0-stable DB=sqlite
|
|
23
|
+
- RAILS=5-1-stable AREL=8-0-stable DB=mysql
|
|
24
|
+
- RAILS=5-1-stable AREL=8-0-stable DB=postgres
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- RAILS=3-2-stable AREL=3-0-stable DB=sqlite
|
|
28
|
-
- RAILS=3-2-stable AREL=3-0-stable DB=mysql
|
|
29
|
-
- RAILS=3-2-stable AREL=3-0-stable DB=postgres
|
|
26
|
+
matrix:
|
|
27
|
+
include:
|
|
28
|
+
- rvm: 2.5.0
|
|
29
|
+
env: RAILS=master DB=sqlite3
|
|
30
|
+
- rvm: 2.5.0
|
|
31
|
+
env: RAILS=master DB=mysql
|
|
32
|
+
- rvm: 2.5.0
|
|
33
|
+
env: RAILS=master DB=postgres
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
- rvm: 2.4.3
|
|
36
|
+
env: RAILS=master DB=sqlite3
|
|
37
|
+
- rvm: 2.4.3
|
|
38
|
+
env: RAILS=master DB=mysql
|
|
39
|
+
- rvm: 2.4.3
|
|
40
|
+
env: RAILS=master DB=postgres
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
- rvm: 2.3.6
|
|
43
|
+
env: RAILS=master DB=sqlite3
|
|
44
|
+
- rvm: 2.3.6
|
|
45
|
+
env: RAILS=master DB=mysql
|
|
46
|
+
- rvm: 2.3.6
|
|
47
|
+
env: RAILS=master DB=postgres
|
|
38
48
|
|
|
39
|
-
|
|
40
|
-
include:
|
|
41
|
-
- rvm: 2.2.1
|
|
49
|
+
- rvm: 2.2.9
|
|
42
50
|
env: RAILS=master DB=sqlite3
|
|
43
|
-
- rvm: 2.2.
|
|
51
|
+
- rvm: 2.2.9
|
|
44
52
|
env: RAILS=master DB=mysql
|
|
45
|
-
- rvm: 2.2.
|
|
53
|
+
- rvm: 2.2.9
|
|
46
54
|
env: RAILS=master DB=postgres
|
|
47
|
-
allow_failures:
|
|
48
|
-
- env: RAILS=master DB=sqlite3
|
|
49
|
-
- env: RAILS=master DB=mysql
|
|
50
|
-
- env: RAILS=master DB=postgres
|
|
51
55
|
|
|
52
56
|
before_script:
|
|
53
57
|
- mysql -e 'create database ransack collate utf8_general_ci;'
|
data/README.md
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
# Polyamorous
|
|
2
|
+
[](https://travis-ci.org/activerecord-hackery/polyamorous)
|
|
3
|
+
[](https://badge.fury.io/rb/polyamorous)
|
|
4
|
+
[](https://codeclimate.com/github/activerecord-hackery/polyamorous)
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
(https://
|
|
5
|
-
[
|
|
6
|
-
(
|
|
7
|
-
|
|
8
|
-
Polyamorous is an extraction from MetaSearch 1.1.x, Ransack, and Squeel by
|
|
6
|
+
Polyamorous is an extraction of shared code from the
|
|
7
|
+
[Active Record Hackery](https://github.com/activerecord-hackery) gems
|
|
8
|
+
[Ransack](https://github.com/activerecord-hackery/ransack),
|
|
9
|
+
[Squeel](https://github.com/activerecord-hackery/squeel) and
|
|
10
|
+
[MetaSearch](https://github.com/activerecord-hackery/meta_search) by
|
|
9
11
|
[Ernie Miller](http://twitter.com/erniemiller) and maintained by
|
|
10
12
|
[Ryan Bigg](http://twitter.com/ryanbigg),
|
|
11
13
|
[Xiang Li](http://bigxiang.github.io),
|
|
12
|
-
[Jon Atack](http://twitter.com/jonatack)
|
|
14
|
+
[Jon Atack](http://twitter.com/jonatack),
|
|
15
|
+
[Sean Carroll](https://github.com/seanfcarroll) and a great little group of
|
|
13
16
|
[contributors]
|
|
14
17
|
(https://github.com/activerecord-hackery/polyamorous/graphs/contributors).
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
It is an internal library for extending various versions of Active Record with
|
|
20
|
+
polymorphism. There is no public API, so it's `:nodoc:`. Move along. Nothing to
|
|
21
|
+
see here.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# active_record_4.1_ruby_1.9/join_dependency.rb
|
|
2
2
|
require 'polyamorous/activerecord_4.2_ruby_2/join_dependency'
|
|
3
3
|
require 'polyamorous/activerecord_4.2_ruby_1.9/join_dependency'
|
|
4
|
-
require 'polyamorous/activerecord_4.1_ruby_2/
|
|
4
|
+
require 'polyamorous/activerecord_4.1_ruby_2/make_polyamorous_inner_joins'
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# active_record_4.1_ruby_2/join_association.rb
|
|
2
|
-
require 'polyamorous/
|
|
2
|
+
require 'polyamorous/activerecord_5.0_ruby_2/join_association'
|
data/lib/polyamorous/activerecord_4.1_ruby_2/{make_joins.rb → make_polyamorous_inner_joins.rb}
RENAMED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
module Polyamorous
|
|
2
2
|
module JoinDependencyExtensions
|
|
3
3
|
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
|
|
4
|
-
|
|
4
|
+
#
|
|
5
|
+
def make_polyamorous_inner_joins(parent, child)
|
|
5
6
|
make_constraints(
|
|
6
7
|
parent, child, child.tables, child.join_type || Arel::Nodes::InnerJoin
|
|
7
8
|
)
|
|
8
|
-
.concat child.children.flat_map { |c|
|
|
9
|
+
.concat child.children.flat_map { |c|
|
|
10
|
+
make_polyamorous_inner_joins(child, c)
|
|
11
|
+
}
|
|
9
12
|
end
|
|
10
13
|
end
|
|
11
14
|
end
|
|
@@ -20,26 +20,18 @@ module Polyamorous
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
# Replaces ActiveRecord::Associations::JoinDependency#build
|
|
23
|
+
#
|
|
23
24
|
def build_with_polymorphism(associations, base_klass)
|
|
24
25
|
associations.map do |name, right|
|
|
25
26
|
if name.is_a? Join
|
|
26
27
|
reflection = find_reflection base_klass, name.name
|
|
27
28
|
reflection.check_validity!
|
|
28
|
-
if reflection.polymorphic?
|
|
29
|
-
|
|
30
|
-
reflection,
|
|
31
|
-
build(right, name.klass || base_klass),
|
|
32
|
-
name.klass,
|
|
33
|
-
name.type
|
|
34
|
-
)
|
|
29
|
+
klass = if reflection.polymorphic?
|
|
30
|
+
name.klass || base_klass
|
|
35
31
|
else
|
|
36
|
-
|
|
37
|
-
reflection,
|
|
38
|
-
build(right, reflection.klass),
|
|
39
|
-
name.klass,
|
|
40
|
-
name.type
|
|
41
|
-
)
|
|
32
|
+
reflection.klass
|
|
42
33
|
end
|
|
34
|
+
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
|
43
35
|
else
|
|
44
36
|
reflection = find_reflection base_klass, name
|
|
45
37
|
reflection.check_validity!
|
|
@@ -52,10 +44,11 @@ module Polyamorous
|
|
|
52
44
|
end
|
|
53
45
|
|
|
54
46
|
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
|
55
|
-
# to call #
|
|
47
|
+
# to call #make_polyamorous_inner_joins instead of #make_inner_joins
|
|
48
|
+
#
|
|
56
49
|
def join_constraints_with_polymorphism(outer_joins)
|
|
57
50
|
joins = join_root.children.flat_map { |child|
|
|
58
|
-
|
|
51
|
+
make_polyamorous_inner_joins join_root, child
|
|
59
52
|
}
|
|
60
53
|
joins.concat outer_joins.flat_map { |oj|
|
|
61
54
|
if join_root.match? oj.join_root
|
|
@@ -69,7 +62,8 @@ module Polyamorous
|
|
|
69
62
|
end
|
|
70
63
|
|
|
71
64
|
module ClassMethods
|
|
72
|
-
|
|
65
|
+
# Replaces ActiveRecord::Associations::JoinDependency#self.walk_tree
|
|
66
|
+
#
|
|
73
67
|
def walk_tree_with_polymorphism(associations, hash)
|
|
74
68
|
case associations
|
|
75
69
|
when TreeNode
|
|
@@ -77,14 +71,13 @@ module Polyamorous
|
|
|
77
71
|
when Hash
|
|
78
72
|
associations.each do |k, v|
|
|
79
73
|
cache =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
end
|
|
74
|
+
if TreeNode === k
|
|
75
|
+
k.add_to_tree(hash)
|
|
76
|
+
else
|
|
77
|
+
hash[k] ||= {}
|
|
78
|
+
end
|
|
86
79
|
walk_tree(v, cache)
|
|
87
|
-
|
|
80
|
+
end
|
|
88
81
|
else
|
|
89
82
|
walk_tree_without_polymorphism(associations, hash)
|
|
90
83
|
end
|
|
@@ -1,37 +1,2 @@
|
|
|
1
1
|
# active_record_4.2_ruby_2/join_association.rb
|
|
2
|
-
|
|
3
|
-
module JoinAssociationExtensions
|
|
4
|
-
include SwappingReflectionClass
|
|
5
|
-
def self.prepended(base)
|
|
6
|
-
base.class_eval { attr_reader :join_type }
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def initialize(reflection, children, polymorphic_class = nil,
|
|
10
|
-
join_type = Arel::Nodes::InnerJoin)
|
|
11
|
-
@join_type = join_type
|
|
12
|
-
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
|
|
13
|
-
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
|
|
14
|
-
super(reflection, children)
|
|
15
|
-
self.reflection.options[:polymorphic] = true
|
|
16
|
-
end
|
|
17
|
-
else
|
|
18
|
-
super(reflection, children)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Reference https://github.com/rails/rails/commit/9b15db51b78028bfecdb85595624de4b838adbd1
|
|
23
|
-
# NOTE Not sure we still need it?
|
|
24
|
-
def ==(other)
|
|
25
|
-
base_klass == other.base_klass
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def build_constraint(klass, table, key, foreign_table, foreign_key)
|
|
29
|
-
if reflection.polymorphic?
|
|
30
|
-
super(klass, table, key, foreign_table, foreign_key)
|
|
31
|
-
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
|
32
|
-
else
|
|
33
|
-
super(klass, table, key, foreign_table, foreign_key)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
2
|
+
require 'polyamorous/activerecord_5.0_ruby_2/join_association'
|
|
@@ -1,61 +1,14 @@
|
|
|
1
1
|
# active_record_4.2_ruby_2/join_dependency.rb
|
|
2
|
+
require 'polyamorous/activerecord_5.0_ruby_2/join_dependency'
|
|
3
|
+
|
|
2
4
|
module Polyamorous
|
|
3
5
|
module JoinDependencyExtensions
|
|
4
|
-
# Replaces ActiveRecord::Associations::JoinDependency#build
|
|
5
|
-
def build(associations, base_klass)
|
|
6
|
-
associations.map do |name, right|
|
|
7
|
-
if name.is_a? Join
|
|
8
|
-
reflection = find_reflection base_klass, name.name
|
|
9
|
-
reflection.check_validity!
|
|
10
|
-
if reflection.polymorphic?
|
|
11
|
-
JoinAssociation.new(
|
|
12
|
-
reflection,
|
|
13
|
-
build(right, name.klass || base_klass),
|
|
14
|
-
name.klass,
|
|
15
|
-
name.type
|
|
16
|
-
)
|
|
17
|
-
else
|
|
18
|
-
JoinAssociation.new(
|
|
19
|
-
reflection,
|
|
20
|
-
build(right, reflection.klass),
|
|
21
|
-
name.klass,
|
|
22
|
-
name.type
|
|
23
|
-
)
|
|
24
|
-
end
|
|
25
|
-
else
|
|
26
|
-
reflection = find_reflection base_klass, name
|
|
27
|
-
reflection.check_validity!
|
|
28
|
-
if reflection.polymorphic?
|
|
29
|
-
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
|
30
|
-
end
|
|
31
|
-
JoinAssociation.new reflection, build(right, reflection.klass)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def find_join_association_respecting_polymorphism(reflection, parent, klass)
|
|
37
|
-
if association = parent.children.find { |j| j.reflection == reflection }
|
|
38
|
-
unless reflection.polymorphic?
|
|
39
|
-
association
|
|
40
|
-
else
|
|
41
|
-
association if association.base_klass == klass
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def build_join_association_respecting_polymorphism(reflection, parent, klass)
|
|
47
|
-
if reflection.polymorphic? && klass
|
|
48
|
-
JoinAssociation.new(reflection, self, klass)
|
|
49
|
-
else
|
|
50
|
-
JoinAssociation.new(reflection, self)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
6
|
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
|
55
|
-
# to call #
|
|
7
|
+
# to call #make_polyamorous_inner_joins instead of #make_inner_joins.
|
|
8
|
+
#
|
|
56
9
|
def join_constraints(outer_joins)
|
|
57
10
|
joins = join_root.children.flat_map { |child|
|
|
58
|
-
|
|
11
|
+
make_polyamorous_inner_joins join_root, child
|
|
59
12
|
}
|
|
60
13
|
joins.concat outer_joins.flat_map { |oj|
|
|
61
14
|
if join_root.match? oj.join_root
|
|
@@ -67,39 +20,5 @@ module Polyamorous
|
|
|
67
20
|
end
|
|
68
21
|
}
|
|
69
22
|
end
|
|
70
|
-
|
|
71
|
-
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
|
|
72
|
-
def make_joins(parent, child)
|
|
73
|
-
[
|
|
74
|
-
make_constraints(
|
|
75
|
-
parent, child, child.tables, child.join_type || Arel::Nodes::InnerJoin
|
|
76
|
-
)
|
|
77
|
-
] + child.children.flat_map { |c| make_inner_joins(child, c) }
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
private :make_joins
|
|
81
|
-
|
|
82
|
-
module ClassMethods
|
|
83
|
-
# Prepended before ActiveRecord::Associations::JoinDependency#self.walk_tree
|
|
84
|
-
def walk_tree(associations, hash)
|
|
85
|
-
case associations
|
|
86
|
-
when TreeNode
|
|
87
|
-
associations.add_to_tree(hash)
|
|
88
|
-
when Hash
|
|
89
|
-
associations.each do |k, v|
|
|
90
|
-
cache =
|
|
91
|
-
case k
|
|
92
|
-
when TreeNode
|
|
93
|
-
k.add_to_tree(hash)
|
|
94
|
-
else
|
|
95
|
-
hash[k] ||= {}
|
|
96
|
-
end
|
|
97
|
-
walk_tree(v, cache)
|
|
98
|
-
end
|
|
99
|
-
else
|
|
100
|
-
super(associations, hash)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
23
|
end
|
|
105
24
|
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# active_record_5.1_ruby_2/join_association.rb
|
|
2
|
+
|
|
3
|
+
module Polyamorous
|
|
4
|
+
module JoinAssociationExtensions
|
|
5
|
+
include SwappingReflectionClass
|
|
6
|
+
def self.prepended(base)
|
|
7
|
+
base.class_eval { attr_reader :join_type }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(reflection, children, polymorphic_class = nil,
|
|
11
|
+
join_type = Arel::Nodes::InnerJoin)
|
|
12
|
+
@join_type = join_type
|
|
13
|
+
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
|
|
14
|
+
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
|
|
15
|
+
super(reflection, children)
|
|
16
|
+
self.reflection.options[:polymorphic] = true
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
super(reflection, children)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Reference: https://github.com/rails/rails/commit/9b15db5
|
|
24
|
+
# NOTE: Not sure we still need it?
|
|
25
|
+
#
|
|
26
|
+
def ==(other)
|
|
27
|
+
base_klass == other.base_klass
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def build_constraint(klass, table, key, foreign_table, foreign_key)
|
|
31
|
+
if reflection.polymorphic?
|
|
32
|
+
super(klass, table, key, foreign_table, foreign_key)
|
|
33
|
+
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
|
34
|
+
else
|
|
35
|
+
super(klass, table, key, foreign_table, foreign_key)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# active_record_5.1_ruby_2/join_dependency.rb
|
|
2
|
+
|
|
3
|
+
module Polyamorous
|
|
4
|
+
module JoinDependencyExtensions
|
|
5
|
+
# Replaces ActiveRecord::Associations::JoinDependency#build
|
|
6
|
+
#
|
|
7
|
+
def build(associations, base_klass)
|
|
8
|
+
associations.map do |name, right|
|
|
9
|
+
if name.is_a? Join
|
|
10
|
+
reflection = find_reflection base_klass, name.name
|
|
11
|
+
reflection.check_validity!
|
|
12
|
+
reflection.check_eager_loadable! if ActiveRecord::VERSION::MAJOR >= 5
|
|
13
|
+
|
|
14
|
+
klass = if reflection.polymorphic?
|
|
15
|
+
name.klass || base_klass
|
|
16
|
+
else
|
|
17
|
+
reflection.klass
|
|
18
|
+
end
|
|
19
|
+
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
|
20
|
+
else
|
|
21
|
+
reflection = find_reflection base_klass, name
|
|
22
|
+
reflection.check_validity!
|
|
23
|
+
reflection.check_eager_loadable! if ActiveRecord::VERSION::MAJOR >= 5
|
|
24
|
+
|
|
25
|
+
if reflection.polymorphic?
|
|
26
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
|
27
|
+
end
|
|
28
|
+
JoinAssociation.new reflection, build(right, reflection.klass)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def find_join_association_respecting_polymorphism(reflection, parent, klass)
|
|
34
|
+
if association = parent.children.find { |j| j.reflection == reflection }
|
|
35
|
+
unless reflection.polymorphic?
|
|
36
|
+
association
|
|
37
|
+
else
|
|
38
|
+
association if association.base_klass == klass
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def build_join_association_respecting_polymorphism(reflection, parent, klass)
|
|
44
|
+
if reflection.polymorphic? && klass
|
|
45
|
+
JoinAssociation.new(reflection, self, klass)
|
|
46
|
+
else
|
|
47
|
+
JoinAssociation.new(reflection, self)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
|
52
|
+
#
|
|
53
|
+
# This internal method was changed in Rails 5.0 by commit
|
|
54
|
+
# https://github.com/rails/rails/commit/e038975 which added
|
|
55
|
+
# left_outer_joins (see #make_polyamorous_left_outer_joins below) and added
|
|
56
|
+
# passing an additional argument, `join_type`, to #join_constraints.
|
|
57
|
+
#
|
|
58
|
+
def join_constraints(outer_joins, join_type)
|
|
59
|
+
joins = join_root.children.flat_map { |child|
|
|
60
|
+
if join_type == Arel::Nodes::OuterJoin
|
|
61
|
+
make_polyamorous_left_outer_joins join_root, child
|
|
62
|
+
else
|
|
63
|
+
make_polyamorous_inner_joins join_root, child
|
|
64
|
+
end
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
joins.concat outer_joins.flat_map { |oj|
|
|
68
|
+
if join_root.match? oj.join_root
|
|
69
|
+
walk(join_root, oj.join_root)
|
|
70
|
+
else
|
|
71
|
+
oj.join_root.children.flat_map { |child|
|
|
72
|
+
make_outer_joins(oj.join_root, child)
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_left_outer_joins,
|
|
79
|
+
# a new method that was added in Rails 5.0 with the following commit:
|
|
80
|
+
# https://github.com/rails/rails/commit/e038975
|
|
81
|
+
#
|
|
82
|
+
def make_polyamorous_left_outer_joins(parent, child)
|
|
83
|
+
tables = child.tables
|
|
84
|
+
join_type = Arel::Nodes::OuterJoin
|
|
85
|
+
info = make_constraints parent, child, tables, join_type
|
|
86
|
+
|
|
87
|
+
[info] + child.children.flat_map { |c|
|
|
88
|
+
make_polyamorous_left_outer_joins(child, c)
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
|
|
93
|
+
#
|
|
94
|
+
def make_polyamorous_inner_joins(parent, child)
|
|
95
|
+
tables = child.tables
|
|
96
|
+
join_type = child.join_type || Arel::Nodes::InnerJoin
|
|
97
|
+
info = make_constraints parent, child, tables, join_type
|
|
98
|
+
|
|
99
|
+
[info] + child.children.flat_map { |c|
|
|
100
|
+
make_polyamorous_inner_joins(child, c)
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private :make_polyamorous_inner_joins, :make_polyamorous_left_outer_joins
|
|
105
|
+
|
|
106
|
+
module ClassMethods
|
|
107
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
|
108
|
+
#
|
|
109
|
+
def walk_tree(associations, hash)
|
|
110
|
+
case associations
|
|
111
|
+
when TreeNode
|
|
112
|
+
associations.add_to_tree(hash)
|
|
113
|
+
when Hash
|
|
114
|
+
associations.each do |k, v|
|
|
115
|
+
cache =
|
|
116
|
+
if TreeNode === k
|
|
117
|
+
k.add_to_tree(hash)
|
|
118
|
+
else
|
|
119
|
+
hash[k] ||= {}
|
|
120
|
+
end
|
|
121
|
+
walk_tree(v, cache)
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
super(associations, hash)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# active_record_5.2_ruby_2/join_association.rb
|
|
2
|
+
|
|
3
|
+
module Polyamorous
|
|
4
|
+
module JoinAssociationExtensions
|
|
5
|
+
include SwappingReflectionClass
|
|
6
|
+
def self.prepended(base)
|
|
7
|
+
base.class_eval { attr_reader :join_type }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(reflection, children, alias_tracker, polymorphic_class = nil,
|
|
11
|
+
join_type = Arel::Nodes::InnerJoin)
|
|
12
|
+
@join_type = join_type
|
|
13
|
+
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
|
|
14
|
+
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
|
|
15
|
+
super(reflection, children, alias_tracker)
|
|
16
|
+
self.reflection.options[:polymorphic] = true
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
super(reflection, children, alias_tracker)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Reference: https://github.com/rails/rails/commit/9b15db5
|
|
24
|
+
# NOTE: Not sure we still need it?
|
|
25
|
+
#
|
|
26
|
+
def ==(other)
|
|
27
|
+
base_klass == other.base_klass
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def build_constraint(klass, table, key, foreign_table, foreign_key)
|
|
31
|
+
if reflection.polymorphic?
|
|
32
|
+
super(klass, table, key, foreign_table, foreign_key)
|
|
33
|
+
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
|
34
|
+
else
|
|
35
|
+
super(klass, table, key, foreign_table, foreign_key)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# active_record_5.2_ruby_2/join_dependency.rb
|
|
2
|
+
|
|
3
|
+
module Polyamorous
|
|
4
|
+
module JoinDependencyExtensions
|
|
5
|
+
# Replaces ActiveRecord::Associations::JoinDependency#build
|
|
6
|
+
#
|
|
7
|
+
def build(associations, base_klass)
|
|
8
|
+
associations.map do |name, right|
|
|
9
|
+
if name.is_a? Join
|
|
10
|
+
reflection = find_reflection base_klass, name.name
|
|
11
|
+
reflection.check_validity!
|
|
12
|
+
reflection.check_eager_loadable! if ActiveRecord::VERSION::MAJOR >= 5
|
|
13
|
+
|
|
14
|
+
klass = if reflection.polymorphic?
|
|
15
|
+
name.klass || base_klass
|
|
16
|
+
else
|
|
17
|
+
reflection.klass
|
|
18
|
+
end
|
|
19
|
+
JoinAssociation.new(reflection, build(right, klass), alias_tracker, name.klass, name.type)
|
|
20
|
+
else
|
|
21
|
+
reflection = find_reflection base_klass, name
|
|
22
|
+
reflection.check_validity!
|
|
23
|
+
reflection.check_eager_loadable! if ActiveRecord::VERSION::MAJOR >= 5
|
|
24
|
+
|
|
25
|
+
if reflection.polymorphic?
|
|
26
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
|
27
|
+
end
|
|
28
|
+
JoinAssociation.new(reflection, build(right, reflection.klass), alias_tracker)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def find_join_association_respecting_polymorphism(reflection, parent, klass)
|
|
34
|
+
if association = parent.children.find { |j| j.reflection == reflection }
|
|
35
|
+
unless reflection.polymorphic?
|
|
36
|
+
association
|
|
37
|
+
else
|
|
38
|
+
association if association.base_klass == klass
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def build_join_association_respecting_polymorphism(reflection, parent, klass)
|
|
44
|
+
if reflection.polymorphic? && klass
|
|
45
|
+
JoinAssociation.new(reflection, self, alias_tracker, klass)
|
|
46
|
+
else
|
|
47
|
+
JoinAssociation.new(reflection, self, alias_tracker)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
|
52
|
+
#
|
|
53
|
+
# This internal method was changed in Rails 5.0 by commit
|
|
54
|
+
# https://github.com/rails/rails/commit/e038975 which added
|
|
55
|
+
# left_outer_joins (see #make_polyamorous_left_outer_joins below) and added
|
|
56
|
+
# passing an additional argument, `join_type`, to #join_constraints.
|
|
57
|
+
#
|
|
58
|
+
def join_constraints(outer_joins, join_type)
|
|
59
|
+
joins = join_root.children.flat_map { |child|
|
|
60
|
+
if join_type == Arel::Nodes::OuterJoin
|
|
61
|
+
make_polyamorous_left_outer_joins join_root, child
|
|
62
|
+
else
|
|
63
|
+
make_polyamorous_inner_joins join_root, child
|
|
64
|
+
end
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
joins.concat outer_joins.flat_map { |oj|
|
|
68
|
+
if join_root.match? oj.join_root
|
|
69
|
+
walk(join_root, oj.join_root)
|
|
70
|
+
else
|
|
71
|
+
oj.join_root.children.flat_map { |child|
|
|
72
|
+
make_outer_joins(oj.join_root, child)
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_left_outer_joins,
|
|
79
|
+
# a new method that was added in Rails 5.0 with the following commit:
|
|
80
|
+
# https://github.com/rails/rails/commit/e038975
|
|
81
|
+
#
|
|
82
|
+
def make_polyamorous_left_outer_joins(parent, child)
|
|
83
|
+
tables = child.tables
|
|
84
|
+
join_type = Arel::Nodes::OuterJoin
|
|
85
|
+
info = make_constraints parent, child, tables, join_type
|
|
86
|
+
|
|
87
|
+
info + child.children.flat_map { |c|
|
|
88
|
+
make_polyamorous_left_outer_joins(child, c)
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
|
|
93
|
+
#
|
|
94
|
+
def make_polyamorous_inner_joins(parent, child)
|
|
95
|
+
tables = child.tables
|
|
96
|
+
join_type = child.join_type || Arel::Nodes::InnerJoin
|
|
97
|
+
info = make_constraints parent, child, tables, join_type
|
|
98
|
+
|
|
99
|
+
info + child.children.flat_map { |c|
|
|
100
|
+
make_polyamorous_inner_joins(child, c)
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private :make_polyamorous_inner_joins, :make_polyamorous_left_outer_joins
|
|
105
|
+
|
|
106
|
+
module ClassMethods
|
|
107
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
|
108
|
+
#
|
|
109
|
+
def walk_tree(associations, hash)
|
|
110
|
+
case associations
|
|
111
|
+
when TreeNode
|
|
112
|
+
associations.add_to_tree(hash)
|
|
113
|
+
when Hash
|
|
114
|
+
associations.each do |k, v|
|
|
115
|
+
cache =
|
|
116
|
+
if TreeNode === k
|
|
117
|
+
k.add_to_tree(hash)
|
|
118
|
+
else
|
|
119
|
+
hash[k] ||= {}
|
|
120
|
+
end
|
|
121
|
+
walk_tree(v, cache)
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
super(associations, hash)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
end
|
data/lib/polyamorous/version.rb
CHANGED
data/lib/polyamorous.rb
CHANGED
|
@@ -25,15 +25,8 @@ if defined?(::ActiveRecord)
|
|
|
25
25
|
require 'polyamorous/join'
|
|
26
26
|
require 'polyamorous/swapping_reflection_class'
|
|
27
27
|
|
|
28
|
-
ar_version =
|
|
29
|
-
|
|
30
|
-
when '4.2', '5.0'
|
|
31
|
-
'4.2'
|
|
32
|
-
when '4.1'
|
|
33
|
-
'4.1'
|
|
34
|
-
else
|
|
35
|
-
'3_and_4.0'
|
|
36
|
-
end
|
|
28
|
+
ar_version = ::ActiveRecord::VERSION::STRING[0,3]
|
|
29
|
+
ar_version = '3_and_4.0' if ar_version < '4.1'
|
|
37
30
|
|
|
38
31
|
method, ruby_version =
|
|
39
32
|
if RUBY_VERSION >= '2.0' && ar_version >= '4.1'
|
data/polyamorous.gemspec
CHANGED
|
@@ -21,9 +21,9 @@ Gem::Specification.new do |s|
|
|
|
21
21
|
s.rubyforge_project = "polyamorous"
|
|
22
22
|
|
|
23
23
|
s.add_dependency 'activerecord', '>= 3.0'
|
|
24
|
-
s.add_development_dependency 'rspec', '~>
|
|
24
|
+
s.add_development_dependency 'rspec', '~> 3'
|
|
25
25
|
s.add_development_dependency 'machinist', '~> 1.0.6'
|
|
26
|
-
s.add_development_dependency 'faker', '~>
|
|
26
|
+
s.add_development_dependency 'faker', '~> 1.6.5'
|
|
27
27
|
s.add_development_dependency 'sqlite3', '~> 1.3.3'
|
|
28
28
|
|
|
29
29
|
s.files = `git ls-files`.split("\n")
|
|
@@ -9,12 +9,18 @@ module PolyamorousHelper
|
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
14
21
|
end
|
|
15
22
|
|
|
16
23
|
def new_join(name, type = Polyamorous::InnerJoin, klass = nil)
|
|
17
24
|
Polyamorous::Join.new name, type, klass
|
|
18
25
|
end
|
|
19
|
-
|
|
20
26
|
end
|
|
@@ -2,10 +2,53 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
module Polyamorous
|
|
4
4
|
describe JoinAssociation do
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
9
52
|
end
|
|
10
53
|
end
|
|
11
54
|
end
|
|
@@ -2,10 +2,101 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
module Polyamorous
|
|
4
4
|
describe JoinDependency do
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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] }
|
|
9
100
|
end
|
|
10
101
|
end
|
|
11
102
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: polyamorous
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ernie Miller
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
14
|
+
date: 2018-01-23 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: activerecord
|
|
@@ -33,14 +33,14 @@ dependencies:
|
|
|
33
33
|
requirements:
|
|
34
34
|
- - "~>"
|
|
35
35
|
- !ruby/object:Gem::Version
|
|
36
|
-
version:
|
|
36
|
+
version: '3'
|
|
37
37
|
type: :development
|
|
38
38
|
prerelease: false
|
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
40
|
requirements:
|
|
41
41
|
- - "~>"
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version:
|
|
43
|
+
version: '3'
|
|
44
44
|
- !ruby/object:Gem::Dependency
|
|
45
45
|
name: machinist
|
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -61,14 +61,14 @@ dependencies:
|
|
|
61
61
|
requirements:
|
|
62
62
|
- - "~>"
|
|
63
63
|
- !ruby/object:Gem::Version
|
|
64
|
-
version:
|
|
64
|
+
version: 1.6.5
|
|
65
65
|
type: :development
|
|
66
66
|
prerelease: false
|
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
|
68
68
|
requirements:
|
|
69
69
|
- - "~>"
|
|
70
70
|
- !ruby/object:Gem::Version
|
|
71
|
-
version:
|
|
71
|
+
version: 1.6.5
|
|
72
72
|
- !ruby/object:Gem::Dependency
|
|
73
73
|
name: sqlite3
|
|
74
74
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,11 +108,17 @@ files:
|
|
|
108
108
|
- lib/polyamorous/activerecord_4.1_ruby_1.9/join_dependency.rb
|
|
109
109
|
- lib/polyamorous/activerecord_4.1_ruby_2/join_association.rb
|
|
110
110
|
- lib/polyamorous/activerecord_4.1_ruby_2/join_dependency.rb
|
|
111
|
-
- lib/polyamorous/activerecord_4.1_ruby_2/
|
|
111
|
+
- lib/polyamorous/activerecord_4.1_ruby_2/make_polyamorous_inner_joins.rb
|
|
112
112
|
- lib/polyamorous/activerecord_4.2_ruby_1.9/join_association.rb
|
|
113
113
|
- lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb
|
|
114
114
|
- lib/polyamorous/activerecord_4.2_ruby_2/join_association.rb
|
|
115
115
|
- lib/polyamorous/activerecord_4.2_ruby_2/join_dependency.rb
|
|
116
|
+
- lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb
|
|
117
|
+
- lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb
|
|
118
|
+
- lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb
|
|
119
|
+
- lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb
|
|
120
|
+
- lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb
|
|
121
|
+
- lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb
|
|
116
122
|
- lib/polyamorous/join.rb
|
|
117
123
|
- lib/polyamorous/swapping_reflection_class.rb
|
|
118
124
|
- lib/polyamorous/tree_node.rb
|
|
@@ -129,10 +135,6 @@ files:
|
|
|
129
135
|
- spec/polyamorous/join_spec.rb
|
|
130
136
|
- spec/spec_helper.rb
|
|
131
137
|
- spec/support/schema.rb
|
|
132
|
-
- spec/support/shared_examples/join_association_3_and_4.0.rb
|
|
133
|
-
- spec/support/shared_examples/join_association_4.1.rb
|
|
134
|
-
- spec/support/shared_examples/join_dependency_3_and_4.0.rb
|
|
135
|
-
- spec/support/shared_examples/join_dependency_4.1.rb
|
|
136
138
|
homepage: https://github.com/activerecord-hackery/polyamorous
|
|
137
139
|
licenses:
|
|
138
140
|
- MIT
|
|
@@ -153,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
153
155
|
version: '0'
|
|
154
156
|
requirements: []
|
|
155
157
|
rubyforge_project: polyamorous
|
|
156
|
-
rubygems_version: 2.
|
|
158
|
+
rubygems_version: 2.6.13
|
|
157
159
|
signing_key:
|
|
158
160
|
specification_version: 4
|
|
159
161
|
summary: Loves/is loved by polymorphic belongs_to associations, Ransack, Squeel, MetaSearch...
|
|
@@ -169,7 +171,3 @@ test_files:
|
|
|
169
171
|
- spec/polyamorous/join_spec.rb
|
|
170
172
|
- spec/spec_helper.rb
|
|
171
173
|
- spec/support/schema.rb
|
|
172
|
-
- spec/support/shared_examples/join_association_3_and_4.0.rb
|
|
173
|
-
- spec/support/shared_examples/join_association_4.1.rb
|
|
174
|
-
- spec/support/shared_examples/join_dependency_3_and_4.0.rb
|
|
175
|
-
- spec/support/shared_examples/join_dependency_4.1.rb
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
shared_examples 'Join Association on ActiveRecord 3 and 4.0' do
|
|
2
|
-
let(:join_dependency) { new_join_dependency Note, {} }
|
|
3
|
-
let(:reflection) { Note.reflect_on_association(:notable) }
|
|
4
|
-
let(:parent) { join_dependency.join_base }
|
|
5
|
-
let(:join_association) {
|
|
6
|
-
new_join_association(reflection, join_dependency, parent, Article)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
subject {
|
|
10
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
|
11
|
-
reflection, parent, Person
|
|
12
|
-
)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
it 'respects polymorphism on equality test' do
|
|
16
|
-
expect(subject).to eq(
|
|
17
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
|
18
|
-
reflection, parent, Person
|
|
19
|
-
)
|
|
20
|
-
)
|
|
21
|
-
expect(subject).not_to eq(
|
|
22
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
|
23
|
-
reflection, parent, Article
|
|
24
|
-
)
|
|
25
|
-
)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it 'leaves the orginal reflection intact for thread safety' do
|
|
29
|
-
reflection.instance_variable_set(:@klass, Article)
|
|
30
|
-
join_association
|
|
31
|
-
.swapping_reflection_klass(reflection, Person) do |new_reflection|
|
|
32
|
-
expect(new_reflection.options).not_to equal reflection.options
|
|
33
|
-
expect(new_reflection.options).not_to have_key(:polymorphic)
|
|
34
|
-
expect(new_reflection.klass).to eq(Person)
|
|
35
|
-
expect(reflection.klass).to eq(Article)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it 'sets the polmorphic option to true after initializing' do
|
|
40
|
-
expect(join_association.options[:polymorphic]).to be_true
|
|
41
|
-
end
|
|
42
|
-
end
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
shared_examples 'Join Association on ActiveRecord 4.1' do
|
|
2
|
-
let(:join_dependency) { new_join_dependency Note, {} }
|
|
3
|
-
let(:reflection) { Note.reflect_on_association(:notable) }
|
|
4
|
-
let(:parent) { join_dependency.join_root }
|
|
5
|
-
let(:join_association) {
|
|
6
|
-
new_join_association(reflection, parent.children, Article)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
subject {
|
|
10
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
|
11
|
-
reflection, parent, Person
|
|
12
|
-
)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
it 'respects polymorphism on equality test' do
|
|
16
|
-
expect(subject).to eq(
|
|
17
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
|
18
|
-
reflection, parent, Person
|
|
19
|
-
)
|
|
20
|
-
)
|
|
21
|
-
expect(subject).not_to eq(
|
|
22
|
-
join_dependency.build_join_association_respecting_polymorphism(
|
|
23
|
-
reflection, parent, Article
|
|
24
|
-
)
|
|
25
|
-
)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it 'leaves the orginal reflection intact for thread safety' do
|
|
29
|
-
reflection.instance_variable_set(:@klass, Article)
|
|
30
|
-
join_association
|
|
31
|
-
.swapping_reflection_klass(reflection, Person) do |new_reflection|
|
|
32
|
-
expect(new_reflection.options).not_to equal reflection.options
|
|
33
|
-
expect(new_reflection.options).not_to have_key(:polymorphic)
|
|
34
|
-
expect(new_reflection.klass).to eq(Person)
|
|
35
|
-
expect(reflection.klass).to eq(Article)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it 'sets the polmorphic option to true after initializing' do
|
|
40
|
-
expect(join_association.reflection.options[:polymorphic]).to be_true
|
|
41
|
-
end
|
|
42
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
shared_examples "Join Dependency on ActiveRecord 3 and 4.0" do
|
|
2
|
-
context 'with symbol joins' do
|
|
3
|
-
subject { new_join_dependency Person, :articles => :comments }
|
|
4
|
-
|
|
5
|
-
specify { expect(subject.join_associations.size).to eq(2) }
|
|
6
|
-
specify { expect(subject.join_associations)
|
|
7
|
-
.to be_all { |a| a.join_type == Polyamorous::InnerJoin } }
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
context 'with has_many :through association' do
|
|
11
|
-
subject { new_join_dependency Person, :authored_article_comments }
|
|
12
|
-
|
|
13
|
-
specify { expect(subject.join_associations.size).to eq(1) }
|
|
14
|
-
specify { expect(subject.join_associations.first.table_name)
|
|
15
|
-
.to eq 'comments' }
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
context 'with outer join' do
|
|
19
|
-
subject { new_join_dependency Person, new_join(:articles, :outer) }
|
|
20
|
-
|
|
21
|
-
specify { expect(subject.join_associations.size).to eq(1) }
|
|
22
|
-
specify { expect(subject.join_associations)
|
|
23
|
-
.to be_all { |a| a.join_type == Polyamorous::OuterJoin } }
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
context 'with nested outer joins' do
|
|
27
|
-
subject { new_join_dependency Person,
|
|
28
|
-
new_join(:articles, :outer) => new_join(:comments, :outer) }
|
|
29
|
-
|
|
30
|
-
specify { expect(subject.join_associations.size).to eq(2) }
|
|
31
|
-
specify { expect(subject.join_associations)
|
|
32
|
-
.to be_all { |a| a.join_type == Polyamorous::OuterJoin } }
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
context 'with polymorphic belongs_to join' do
|
|
36
|
-
subject { new_join_dependency Note, new_join(:notable, :inner, Person) }
|
|
37
|
-
|
|
38
|
-
specify { expect(subject.join_associations.size).to eq(1) }
|
|
39
|
-
specify { expect(subject.join_associations)
|
|
40
|
-
.to be_all { |a| a.join_type == Polyamorous::InnerJoin } }
|
|
41
|
-
specify { expect(subject.join_associations.first.table_name)
|
|
42
|
-
.to eq 'people' }
|
|
43
|
-
|
|
44
|
-
it 'finds a join association respecting polymorphism' do
|
|
45
|
-
parent = subject.join_base
|
|
46
|
-
reflection = Note.reflect_on_association(:notable)
|
|
47
|
-
expect(subject.find_join_association_respecting_polymorphism(
|
|
48
|
-
reflection, parent, Person
|
|
49
|
-
)).to eq subject.join_associations.first
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
context 'with polymorphic belongs_to join and nested symbol join' do
|
|
54
|
-
subject { new_join_dependency Note,
|
|
55
|
-
new_join(:notable, :inner, Person) => :comments }
|
|
56
|
-
|
|
57
|
-
specify { expect(subject.join_associations.size).to eq(2) }
|
|
58
|
-
specify { expect(subject.join_associations)
|
|
59
|
-
.to be_all { |a| a.join_type == Polyamorous::InnerJoin } }
|
|
60
|
-
specify { expect(subject.join_associations.first.table_name)
|
|
61
|
-
.to eq 'people' }
|
|
62
|
-
specify { expect(subject.join_associations[1].table_name)
|
|
63
|
-
.to eq 'comments' }
|
|
64
|
-
end
|
|
65
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
shared_examples "Join Dependency on ActiveRecord 4.1" do
|
|
2
|
-
context 'with symbol joins' do
|
|
3
|
-
subject { new_join_dependency Person, :articles => :comments }
|
|
4
|
-
|
|
5
|
-
specify { expect(subject.join_root.drop(1).size).to eq(2) }
|
|
6
|
-
specify { expect(subject.join_root.drop(1).map(&:join_type))
|
|
7
|
-
.to be_all { Polyamorous::InnerJoin } }
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
context 'with has_many :through association' do
|
|
11
|
-
subject { new_join_dependency Person, :authored_article_comments }
|
|
12
|
-
|
|
13
|
-
specify { expect(subject.join_root.drop(1).size).to eq(1) }
|
|
14
|
-
specify { expect(subject.join_root.drop(1).first.table_name)
|
|
15
|
-
.to eq 'comments' }
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
context 'with outer join' do
|
|
19
|
-
subject { new_join_dependency Person, new_join(:articles, :outer) }
|
|
20
|
-
|
|
21
|
-
specify { expect(subject.join_root.drop(1).size).to eq(1) }
|
|
22
|
-
specify { expect(subject.join_root.drop(1).first.join_type)
|
|
23
|
-
.to eq Polyamorous::OuterJoin }
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
context 'with nested outer joins' do
|
|
27
|
-
subject { new_join_dependency Person,
|
|
28
|
-
new_join(:articles, :outer) => new_join(:comments, :outer) }
|
|
29
|
-
|
|
30
|
-
specify { expect(subject.join_root.drop(1).size).to eq(2) }
|
|
31
|
-
specify { expect(subject.join_root.drop(1).map(&:join_type))
|
|
32
|
-
.to be_all { Polyamorous::OuterJoin } }
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
context 'with polymorphic belongs_to join' do
|
|
36
|
-
subject { new_join_dependency Note, new_join(:notable, :inner, Person) }
|
|
37
|
-
|
|
38
|
-
specify { expect(subject.join_root.drop(1).size).to eq(1) }
|
|
39
|
-
specify { expect(subject.join_root.drop(1).first.join_type)
|
|
40
|
-
.to eq Polyamorous::InnerJoin }
|
|
41
|
-
specify { expect(subject.join_root.drop(1).first.table_name)
|
|
42
|
-
.to eq 'people' }
|
|
43
|
-
|
|
44
|
-
it 'finds a join association respecting polymorphism' do
|
|
45
|
-
parent = subject.join_root
|
|
46
|
-
reflection = Note.reflect_on_association(:notable)
|
|
47
|
-
expect(subject.find_join_association_respecting_polymorphism(
|
|
48
|
-
reflection, parent, Person
|
|
49
|
-
)).to eq subject.join_root.drop(1).first
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
context 'with polymorphic belongs_to join and nested symbol join' do
|
|
54
|
-
subject { new_join_dependency Note,
|
|
55
|
-
new_join(:notable, :inner, Person) => :comments }
|
|
56
|
-
|
|
57
|
-
specify { expect(subject.join_root.drop(1).size).to eq(2) }
|
|
58
|
-
specify { expect(subject.join_root.drop(1).map(&:join_type))
|
|
59
|
-
.to be_all { Polyamorous::InnerJoin } }
|
|
60
|
-
specify { expect(subject.join_root.drop(1).first.table_name)
|
|
61
|
-
.to eq 'people' }
|
|
62
|
-
specify { expect(subject.join_root.drop(1)[1].table_name)
|
|
63
|
-
.to eq 'comments' }
|
|
64
|
-
end
|
|
65
|
-
end
|