temp_poly 2.1.1a
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 +7 -0
- data/lib/polyamorous.rb +30 -0
- 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 +31 -0
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +112 -0
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +31 -0
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +112 -0
- 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/join.rb +70 -0
- data/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/lib/polyamorous/tree_node.rb +7 -0
- data/lib/polyamorous/version.rb +3 -0
- data/polyamorous.gemspec +35 -0
- data/script/push_gem.rb +8 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 41ee2da931ad87e6f8e82e9cf71828e502367f5785910eea3a9b5b1facff996c
|
4
|
+
data.tar.gz: 0cb00db81543a4923ce36acf6a126b83934d6b3f04ed76e0e0a0b625ec91b4a0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 90188608941c02bf139b1a12239ab416c99ddfb07143659c62c138828bd090c6cc157b2e5a053f1a105117eacddbb01e69738bc5313cf71403c3aa205ff07baf
|
7
|
+
data.tar.gz: 61474851ccf35c5ff7fd7df7b8fc18ab84e89101c06c5714bd80923e4aa41d88d2e064fe0ccfe5f426cf79841678f9fdeb46c8ece2da8d051e4066d07e40a08c
|
data/lib/polyamorous.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
if defined?(::ActiveRecord)
|
2
|
+
module Polyamorous
|
3
|
+
InnerJoin = Arel::Nodes::InnerJoin
|
4
|
+
OuterJoin = Arel::Nodes::OuterJoin
|
5
|
+
|
6
|
+
JoinDependency = ::ActiveRecord::Associations::JoinDependency
|
7
|
+
JoinAssociation = ::ActiveRecord::Associations::JoinDependency::JoinAssociation
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'polyamorous/tree_node'
|
11
|
+
require 'polyamorous/join'
|
12
|
+
require 'polyamorous/swapping_reflection_class'
|
13
|
+
|
14
|
+
ar_version = ::ActiveRecord::VERSION::STRING[0,3]
|
15
|
+
ar_version = ::ActiveRecord::VERSION::STRING[0,5] if ar_version >= "5.2" && ::ActiveRecord::VERSION::STRING < "6.0"
|
16
|
+
ar_version = "5.2.1" if ::ActiveRecord::VERSION::STRING >= "5.2.1" && ::ActiveRecord::VERSION::STRING < "6.0"
|
17
|
+
|
18
|
+
%w(join_association join_dependency).each do |file|
|
19
|
+
require "polyamorous/activerecord_#{ar_version}_ruby_2/#{file}"
|
20
|
+
end
|
21
|
+
|
22
|
+
if ar_version >= "5.2.0"
|
23
|
+
require "polyamorous/activerecord_#{ar_version}_ruby_2/reflection.rb"
|
24
|
+
::ActiveRecord::Reflection::AbstractReflection.send(:prepend, Polyamorous::ReflectionExtensions)
|
25
|
+
end
|
26
|
+
|
27
|
+
Polyamorous::JoinDependency.send(:prepend, Polyamorous::JoinDependencyExtensions)
|
28
|
+
Polyamorous::JoinDependency.singleton_class.send(:prepend, Polyamorous::JoinDependencyExtensions::ClassMethods)
|
29
|
+
Polyamorous::JoinAssociation.send(:prepend, Polyamorous::JoinAssociationExtensions)
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
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, 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
|
+
def build_constraint(klass, table, key, foreign_table, foreign_key)
|
23
|
+
if reflection.polymorphic?
|
24
|
+
super(klass, table, key, foreign_table, foreign_key)
|
25
|
+
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
26
|
+
else
|
27
|
+
super(klass, table, key, foreign_table, foreign_key)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,112 @@
|
|
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!
|
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!
|
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
|
+
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
34
|
+
#
|
35
|
+
# This internal method was changed in Rails 5.0 by commit
|
36
|
+
# https://github.com/rails/rails/commit/e038975 which added
|
37
|
+
# left_outer_joins (see #make_polyamorous_left_outer_joins below) and added
|
38
|
+
# passing an additional argument, `join_type`, to #join_constraints.
|
39
|
+
#
|
40
|
+
def join_constraints(outer_joins, join_type)
|
41
|
+
joins = join_root.children.flat_map { |child|
|
42
|
+
if join_type == Arel::Nodes::OuterJoin
|
43
|
+
make_polyamorous_left_outer_joins join_root, child
|
44
|
+
else
|
45
|
+
make_polyamorous_inner_joins join_root, child
|
46
|
+
end
|
47
|
+
}
|
48
|
+
|
49
|
+
joins.concat outer_joins.flat_map { |oj|
|
50
|
+
if join_root.match? oj.join_root
|
51
|
+
walk(join_root, oj.join_root)
|
52
|
+
else
|
53
|
+
oj.join_root.children.flat_map { |child|
|
54
|
+
make_outer_joins(oj.join_root, child)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_left_outer_joins,
|
61
|
+
# a new method that was added in Rails 5.0 with the following commit:
|
62
|
+
# https://github.com/rails/rails/commit/e038975
|
63
|
+
#
|
64
|
+
def make_polyamorous_left_outer_joins(parent, child)
|
65
|
+
tables = child.tables
|
66
|
+
join_type = Arel::Nodes::OuterJoin
|
67
|
+
info = make_constraints parent, child, tables, join_type
|
68
|
+
|
69
|
+
[info] + child.children.flat_map { |c|
|
70
|
+
make_polyamorous_left_outer_joins(child, c)
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
|
75
|
+
#
|
76
|
+
def make_polyamorous_inner_joins(parent, child)
|
77
|
+
tables = child.tables
|
78
|
+
join_type = child.join_type || Arel::Nodes::InnerJoin
|
79
|
+
info = make_constraints parent, child, tables, join_type
|
80
|
+
|
81
|
+
[info] + child.children.flat_map { |c|
|
82
|
+
make_polyamorous_inner_joins(child, c)
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
private :make_polyamorous_inner_joins, :make_polyamorous_left_outer_joins
|
87
|
+
|
88
|
+
module ClassMethods
|
89
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
90
|
+
#
|
91
|
+
def walk_tree(associations, hash)
|
92
|
+
case associations
|
93
|
+
when TreeNode
|
94
|
+
associations.add_to_tree(hash)
|
95
|
+
when Hash
|
96
|
+
associations.each do |k, v|
|
97
|
+
cache =
|
98
|
+
if TreeNode === k
|
99
|
+
k.add_to_tree(hash)
|
100
|
+
else
|
101
|
+
hash[k] ||= {}
|
102
|
+
end
|
103
|
+
walk_tree(v, cache)
|
104
|
+
end
|
105
|
+
else
|
106
|
+
super(associations, hash)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,31 @@
|
|
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, 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, alias_tracker)
|
15
|
+
self.reflection.options[:polymorphic] = true
|
16
|
+
end
|
17
|
+
else
|
18
|
+
super(reflection, children, alias_tracker)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def build_constraint(klass, table, key, foreign_table, foreign_key)
|
23
|
+
if reflection.polymorphic?
|
24
|
+
super(klass, table, key, foreign_table, foreign_key)
|
25
|
+
.and(foreign_table[reflection.foreign_type].eq(reflection.klass.name))
|
26
|
+
else
|
27
|
+
super(klass, table, key, foreign_table, foreign_key)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,112 @@
|
|
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!
|
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!
|
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
|
+
# Replaces ActiveRecord::Associations::JoinDependency#join_constraints
|
34
|
+
#
|
35
|
+
# This internal method was changed in Rails 5.0 by commit
|
36
|
+
# https://github.com/rails/rails/commit/e038975 which added
|
37
|
+
# left_outer_joins (see #make_polyamorous_left_outer_joins below) and added
|
38
|
+
# passing an additional argument, `join_type`, to #join_constraints.
|
39
|
+
#
|
40
|
+
def join_constraints(outer_joins, join_type)
|
41
|
+
joins = join_root.children.flat_map { |child|
|
42
|
+
if join_type == Arel::Nodes::OuterJoin
|
43
|
+
make_polyamorous_left_outer_joins join_root, child
|
44
|
+
else
|
45
|
+
make_polyamorous_inner_joins join_root, child
|
46
|
+
end
|
47
|
+
}
|
48
|
+
|
49
|
+
joins.concat outer_joins.flat_map { |oj|
|
50
|
+
if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name
|
51
|
+
walk(join_root, oj.join_root)
|
52
|
+
else
|
53
|
+
oj.join_root.children.flat_map { |child|
|
54
|
+
make_outer_joins(oj.join_root, child)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_left_outer_joins,
|
61
|
+
# a new method that was added in Rails 5.0 with the following commit:
|
62
|
+
# https://github.com/rails/rails/commit/e038975
|
63
|
+
#
|
64
|
+
def make_polyamorous_left_outer_joins(parent, child)
|
65
|
+
tables = child.tables
|
66
|
+
join_type = Arel::Nodes::OuterJoin
|
67
|
+
info = make_constraints parent, child, tables, join_type
|
68
|
+
|
69
|
+
info + child.children.flat_map { |c|
|
70
|
+
make_polyamorous_left_outer_joins(child, c)
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
# Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins
|
75
|
+
#
|
76
|
+
def make_polyamorous_inner_joins(parent, child)
|
77
|
+
tables = child.tables
|
78
|
+
join_type = child.join_type || Arel::Nodes::InnerJoin
|
79
|
+
info = make_constraints parent, child, tables, join_type
|
80
|
+
|
81
|
+
info + child.children.flat_map { |c|
|
82
|
+
make_polyamorous_inner_joins(child, c)
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
private :make_polyamorous_inner_joins, :make_polyamorous_left_outer_joins
|
87
|
+
|
88
|
+
module ClassMethods
|
89
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
90
|
+
#
|
91
|
+
def walk_tree(associations, hash)
|
92
|
+
case associations
|
93
|
+
when TreeNode
|
94
|
+
associations.add_to_tree(hash)
|
95
|
+
when Hash
|
96
|
+
associations.each do |k, v|
|
97
|
+
cache =
|
98
|
+
if TreeNode === k
|
99
|
+
k.add_to_tree(hash)
|
100
|
+
else
|
101
|
+
hash[k] ||= {}
|
102
|
+
end
|
103
|
+
walk_tree(v, cache)
|
104
|
+
end
|
105
|
+
else
|
106
|
+
super(associations, hash)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Polyamorous
|
2
|
+
module ReflectionExtensions
|
3
|
+
def build_join_constraint(table, foreign_table)
|
4
|
+
if polymorphic?
|
5
|
+
super(table, foreign_table)
|
6
|
+
.and(foreign_table[foreign_type].eq(klass.name))
|
7
|
+
else
|
8
|
+
super(table, foreign_table)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# active_record_5.2.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, 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
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# active_record_5.2.1_ruby_2/join_dependency.rb
|
2
|
+
|
3
|
+
module Polyamorous
|
4
|
+
module JoinDependencyExtensions
|
5
|
+
# Replaces ActiveRecord::Associations::JoinDependency#build
|
6
|
+
def build(associations, base_klass)
|
7
|
+
associations.map do |name, right|
|
8
|
+
if name.is_a? Join
|
9
|
+
reflection = find_reflection base_klass, name.name
|
10
|
+
reflection.check_validity!
|
11
|
+
reflection.check_eager_loadable!
|
12
|
+
|
13
|
+
klass = if reflection.polymorphic?
|
14
|
+
name.klass || base_klass
|
15
|
+
else
|
16
|
+
reflection.klass
|
17
|
+
end
|
18
|
+
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
19
|
+
else
|
20
|
+
reflection = find_reflection base_klass, name
|
21
|
+
reflection.check_validity!
|
22
|
+
reflection.check_eager_loadable!
|
23
|
+
|
24
|
+
if reflection.polymorphic?
|
25
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
26
|
+
end
|
27
|
+
JoinAssociation.new(reflection, build(right, reflection.klass))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def join_constraints(joins_to_add, join_type, alias_tracker)
|
33
|
+
@alias_tracker = alias_tracker
|
34
|
+
|
35
|
+
construct_tables!(join_root)
|
36
|
+
joins = make_join_constraints(join_root, join_type)
|
37
|
+
|
38
|
+
joins.concat joins_to_add.flat_map { |oj|
|
39
|
+
construct_tables!(oj.join_root)
|
40
|
+
if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name
|
41
|
+
walk join_root, oj.join_root
|
42
|
+
else
|
43
|
+
make_join_constraints(oj.join_root, join_type)
|
44
|
+
end
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def make_constraints(parent, child, join_type = Arel::Nodes::OuterJoin)
|
50
|
+
foreign_table = parent.table
|
51
|
+
foreign_klass = parent.base_klass
|
52
|
+
join_type = child.join_type || join_type if join_type == Arel::Nodes::InnerJoin
|
53
|
+
joins = child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
|
54
|
+
joins.concat child.children.flat_map { |c| make_constraints(child, c, join_type) }
|
55
|
+
end
|
56
|
+
|
57
|
+
module ClassMethods
|
58
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
59
|
+
#
|
60
|
+
def walk_tree(associations, hash)
|
61
|
+
case associations
|
62
|
+
when TreeNode
|
63
|
+
associations.add_to_tree(hash)
|
64
|
+
when Hash
|
65
|
+
associations.each do |k, v|
|
66
|
+
cache =
|
67
|
+
if TreeNode === k
|
68
|
+
k.add_to_tree(hash)
|
69
|
+
else
|
70
|
+
hash[k] ||= {}
|
71
|
+
end
|
72
|
+
walk_tree(v, cache)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
super(associations, hash)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# active_record_6.0_ruby_2/join_dependency.rb
|
2
|
+
|
3
|
+
module Polyamorous
|
4
|
+
module JoinDependencyExtensions
|
5
|
+
# Replaces ActiveRecord::Associations::JoinDependency#build
|
6
|
+
def build(associations, base_klass)
|
7
|
+
associations.map do |name, right|
|
8
|
+
if name.is_a? Join
|
9
|
+
reflection = find_reflection base_klass, name.name
|
10
|
+
reflection.check_validity!
|
11
|
+
reflection.check_eager_loadable!
|
12
|
+
|
13
|
+
klass = if reflection.polymorphic?
|
14
|
+
name.klass || base_klass
|
15
|
+
else
|
16
|
+
reflection.klass
|
17
|
+
end
|
18
|
+
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
19
|
+
else
|
20
|
+
reflection = find_reflection base_klass, name
|
21
|
+
reflection.check_validity!
|
22
|
+
reflection.check_eager_loadable!
|
23
|
+
|
24
|
+
if reflection.polymorphic?
|
25
|
+
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
26
|
+
end
|
27
|
+
JoinAssociation.new(reflection, build(right, reflection.klass))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def join_constraints(joins_to_add, alias_tracker)
|
33
|
+
@alias_tracker = alias_tracker
|
34
|
+
|
35
|
+
construct_tables!(join_root)
|
36
|
+
joins = make_join_constraints(join_root, join_type)
|
37
|
+
|
38
|
+
joins.concat joins_to_add.flat_map { |oj|
|
39
|
+
construct_tables!(oj.join_root)
|
40
|
+
if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name
|
41
|
+
walk join_root, oj.join_root, oj.join_type
|
42
|
+
else
|
43
|
+
make_join_constraints(oj.join_root, oj.join_type)
|
44
|
+
end
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def make_constraints(parent, child, join_type = Arel::Nodes::OuterJoin)
|
50
|
+
foreign_table = parent.table
|
51
|
+
foreign_klass = parent.base_klass
|
52
|
+
join_type = child.join_type || join_type if join_type == Arel::Nodes::InnerJoin
|
53
|
+
joins = child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
|
54
|
+
joins.concat child.children.flat_map { |c| make_constraints(child, c, join_type) }
|
55
|
+
end
|
56
|
+
|
57
|
+
module ClassMethods
|
58
|
+
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
59
|
+
#
|
60
|
+
def walk_tree(associations, hash)
|
61
|
+
case associations
|
62
|
+
when TreeNode
|
63
|
+
associations.add_to_tree(hash)
|
64
|
+
when Hash
|
65
|
+
associations.each do |k, v|
|
66
|
+
cache =
|
67
|
+
if TreeNode === k
|
68
|
+
k.add_to_tree(hash)
|
69
|
+
else
|
70
|
+
hash[k] ||= {}
|
71
|
+
end
|
72
|
+
walk_tree(v, cache)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
super(associations, hash)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Polyamorous
|
2
|
+
class Join
|
3
|
+
include TreeNode
|
4
|
+
|
5
|
+
attr_accessor :name
|
6
|
+
attr_reader :type, :klass
|
7
|
+
|
8
|
+
def initialize(name, type = InnerJoin, klass = nil)
|
9
|
+
@name = name
|
10
|
+
@type = convert_to_arel_join_type(type)
|
11
|
+
@klass = convert_to_class(klass) if klass
|
12
|
+
end
|
13
|
+
|
14
|
+
def klass=(klass)
|
15
|
+
@klass = convert_to_class(klass) if klass
|
16
|
+
end
|
17
|
+
|
18
|
+
def type=(type)
|
19
|
+
@type = convert_to_arel_join_type(type) if type
|
20
|
+
end
|
21
|
+
|
22
|
+
def hash
|
23
|
+
[@name, @type, @klass].hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def eql?(other)
|
27
|
+
self.class == other.class &&
|
28
|
+
self.name == other.name &&
|
29
|
+
self.type == other.type &&
|
30
|
+
self.klass == other.klass
|
31
|
+
end
|
32
|
+
|
33
|
+
alias :== :eql?
|
34
|
+
|
35
|
+
def add_to_tree(hash)
|
36
|
+
hash[self] ||= {}
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def convert_to_arel_join_type(type)
|
42
|
+
case type
|
43
|
+
when 'inner', :inner
|
44
|
+
InnerJoin
|
45
|
+
when 'outer', :outer
|
46
|
+
OuterJoin
|
47
|
+
when Class
|
48
|
+
if [InnerJoin, OuterJoin].include? type
|
49
|
+
type
|
50
|
+
else
|
51
|
+
raise ArgumentError, "#{type} cannot be converted to an ARel join type"
|
52
|
+
end
|
53
|
+
else
|
54
|
+
raise ArgumentError, "#{type} cannot be converted to an ARel join type"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert_to_class(value)
|
59
|
+
case value
|
60
|
+
when String, Symbol
|
61
|
+
Kernel.const_get(value)
|
62
|
+
when Class
|
63
|
+
value
|
64
|
+
else
|
65
|
+
raise ArgumentError, "#{value} cannot be converted to a Class"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Polyamorous
|
2
|
+
module SwappingReflectionClass
|
3
|
+
def swapping_reflection_klass(reflection, klass)
|
4
|
+
new_reflection = reflection.clone
|
5
|
+
new_reflection.instance_variable_set(:@options, reflection.options.clone)
|
6
|
+
new_reflection.options.delete(:polymorphic)
|
7
|
+
new_reflection.instance_variable_set(:@klass, klass)
|
8
|
+
yield new_reflection
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/polyamorous.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "polyamorous/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "temp_poly"
|
7
|
+
s.version = Polyamorous::VERSION
|
8
|
+
s.authors = ["To be announced"]
|
9
|
+
s.email = []
|
10
|
+
s.homepage = "https://github.com/activerecord-hackery/ransack/tree/master/polyamorous"
|
11
|
+
s.license = "MIT"
|
12
|
+
s.summary = %q{
|
13
|
+
A temporary gem to test build, do not download
|
14
|
+
}
|
15
|
+
s.description = %q{
|
16
|
+
A temporary gem to test build, do not download.
|
17
|
+
}
|
18
|
+
|
19
|
+
s.rubyforge_project = "polyamorous"
|
20
|
+
|
21
|
+
s.add_dependency 'activerecord', '>= 5.0'
|
22
|
+
s.add_development_dependency 'rspec', '~> 3'
|
23
|
+
s.add_development_dependency 'machinist', '~> 1.0.6'
|
24
|
+
s.add_development_dependency 'faker', '~> 1.6.5'
|
25
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.3'
|
26
|
+
|
27
|
+
s.files = `git ls-files`.split("\n")
|
28
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
29
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
30
|
+
s.require_paths = ["lib"]
|
31
|
+
|
32
|
+
# specify any dependencies here; for example:
|
33
|
+
# s.add_development_dependency "rspec"
|
34
|
+
# s.add_runtime_dependency "rest-client"
|
35
|
+
end
|
data/script/push_gem.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# bash file to push gem to rubygems.org
|
3
|
+
file = File.join File.dirname(__dir__), '/lib/polyamorous/version.rb'
|
4
|
+
require file
|
5
|
+
puts "Build v#{Polyamorous::VERSION} of temp_poly"
|
6
|
+
`gem build polyamorous`
|
7
|
+
`gem push temp_poly-#{Polyamorous::VERSION}.gem`
|
8
|
+
puts "pushed v#{Polyamorous::VERSION} to rubygems"
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: temp_poly
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.1.1a
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- To be announced
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-07-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: machinist
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.0.6
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.6
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faker
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.6.5
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.6.5
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.3.3
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.3.3
|
83
|
+
description: "\n A temporary gem to test build, do not download.\n "
|
84
|
+
email: []
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files: []
|
88
|
+
files:
|
89
|
+
- lib/polyamorous.rb
|
90
|
+
- lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb
|
91
|
+
- lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb
|
92
|
+
- lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb
|
93
|
+
- lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb
|
94
|
+
- lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb
|
95
|
+
- lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb
|
96
|
+
- lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb
|
97
|
+
- lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb
|
98
|
+
- lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb
|
99
|
+
- lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb
|
100
|
+
- lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb
|
101
|
+
- lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb
|
102
|
+
- lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb
|
103
|
+
- lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb
|
104
|
+
- lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb
|
105
|
+
- lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb
|
106
|
+
- lib/polyamorous/join.rb
|
107
|
+
- lib/polyamorous/swapping_reflection_class.rb
|
108
|
+
- lib/polyamorous/tree_node.rb
|
109
|
+
- lib/polyamorous/version.rb
|
110
|
+
- polyamorous.gemspec
|
111
|
+
- script/push_gem.rb
|
112
|
+
homepage: https://github.com/activerecord-hackery/ransack/tree/master/polyamorous
|
113
|
+
licenses:
|
114
|
+
- MIT
|
115
|
+
metadata: {}
|
116
|
+
post_install_message:
|
117
|
+
rdoc_options: []
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: 1.3.1
|
130
|
+
requirements: []
|
131
|
+
rubygems_version: 3.0.3
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: A temporary gem to test build, do not download
|
135
|
+
test_files: []
|