ar-preloader 1.0.0 → 1.1.0
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/lib/ar/preloader.rb +76 -10
- data/lib/ar/preloader/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d895597b76cd8b4d0264a01a1edbd02dae18d12
|
4
|
+
data.tar.gz: aef0a1676a11b7a1d6d9c802415d52c976913342
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: baf8de3beb914d202cb72431db24a71ccb0844d97353ce06211450aa2bebcc2d522ef43b83ea0dc52314378d0626966b1e720de409b8b8c796bc1381ca05ecd4
|
7
|
+
data.tar.gz: a7407f60a72dfacb079ac3426f0d97a39bc2b84050a8a211a12cf41899c202d4085edb600c6302770f93b2842c4de99773483223c7b1a88e760b7b54bf473bcb
|
data/lib/ar/preloader.rb
CHANGED
@@ -9,6 +9,10 @@ module Ar
|
|
9
9
|
case association
|
10
10
|
when String, Symbol
|
11
11
|
return klass.reflections.keys.include?(association.to_s)
|
12
|
+
when Array
|
13
|
+
association.each do |v|
|
14
|
+
return false unless Ar::Preloader.check_association_exists(klass, v)
|
15
|
+
end
|
12
16
|
when Hash
|
13
17
|
association.each_pair do |k,v|
|
14
18
|
return false unless klass.reflections.keys.include?(k.to_s)
|
@@ -38,6 +42,8 @@ module Ar
|
|
38
42
|
case association
|
39
43
|
when String, Symbol
|
40
44
|
klass = list.first.class
|
45
|
+
klass.send :attr_reader, "_#{association}".to_sym
|
46
|
+
|
41
47
|
association_details = klass.reflections[association.to_s]
|
42
48
|
association_klass = association_details.class_name.constantize
|
43
49
|
|
@@ -46,6 +52,11 @@ module Ar
|
|
46
52
|
foreign_key = association_details.foreign_key
|
47
53
|
association_pk = association_klass.primary_key
|
48
54
|
|
55
|
+
list.each do |obj|
|
56
|
+
instance_variable_name = "@_#{association}".to_sym
|
57
|
+
obj.instance_variable_set(instance_variable_name, [])
|
58
|
+
end
|
59
|
+
|
49
60
|
query = <<-EOS
|
50
61
|
SELECT
|
51
62
|
distinct #{association_klass.table_name}.*
|
@@ -56,15 +67,14 @@ EOS
|
|
56
67
|
|
57
68
|
association_list = association_klass.find_by_sql(query).to_a
|
58
69
|
|
59
|
-
|
70
|
+
if inner_associations.is_a?(Array)
|
71
|
+
association_list.preload(*inner_associations)
|
72
|
+
else
|
73
|
+
association_list.preload(inner_associations)
|
74
|
+
end
|
60
75
|
|
61
76
|
list.each do |obj|
|
62
|
-
klass.send :attr_reader, "_#{association}".to_sym
|
63
|
-
|
64
77
|
instance_variable_name = "@_#{association}".to_sym
|
65
|
-
if obj.instance_variable_get(instance_variable_name).nil?
|
66
|
-
obj.instance_variable_set(instance_variable_name, [])
|
67
|
-
end
|
68
78
|
|
69
79
|
association_list.select{ |e| e[foreign_key.to_sym] == obj[klass.primary_key.to_sym] }.each do |association_obj|
|
70
80
|
each_list = obj.instance_variable_get(instance_variable_name)
|
@@ -76,6 +86,10 @@ EOS
|
|
76
86
|
foreign_key = association_details.foreign_key
|
77
87
|
association_pk = association_klass.primary_key
|
78
88
|
|
89
|
+
if list.map{ |e| e[foreign_key.to_sym] }.compact.length == 0
|
90
|
+
return true
|
91
|
+
end
|
92
|
+
|
79
93
|
query = <<-EOS
|
80
94
|
SELECT
|
81
95
|
distinct #{association_klass.table_name}.*
|
@@ -86,22 +100,73 @@ EOS
|
|
86
100
|
|
87
101
|
association_list = association_klass.find_by_sql(query).to_a
|
88
102
|
|
89
|
-
|
103
|
+
if inner_associations.is_a?(Array)
|
104
|
+
association_list.preload(*inner_associations)
|
105
|
+
else
|
106
|
+
association_list.preload(inner_associations)
|
107
|
+
end
|
90
108
|
|
91
109
|
association_map = association_list.map{ |e| [e[e.class.primary_key.to_sym], e] }.to_h
|
92
110
|
|
93
111
|
list.each do |obj|
|
94
112
|
if obj[foreign_key.to_sym].present? && association_map[obj[foreign_key.to_sym]].present?
|
95
|
-
klass.send :attr_reader, "_#{association}".to_sym
|
96
113
|
obj.instance_variable_set( "@_#{association}".to_sym, association_map[obj[foreign_key.to_sym]] )
|
97
114
|
end
|
98
115
|
end
|
116
|
+
when ActiveRecord::Reflection::HasAndBelongsToManyReflection
|
117
|
+
foreign_key = association_details.foreign_key
|
118
|
+
association_foreign_key = association_details.association_foreign_key
|
119
|
+
join_table = association_details.join_table
|
120
|
+
|
121
|
+
list.each do |obj|
|
122
|
+
instance_variable_name = "@_#{association}".to_sym
|
123
|
+
obj.instance_variable_set(instance_variable_name, [])
|
124
|
+
end
|
125
|
+
|
126
|
+
join_query = <<-EOS
|
127
|
+
SELECT
|
128
|
+
#{join_table}.#{foreign_key},
|
129
|
+
#{join_table}.#{association_foreign_key}
|
130
|
+
FROM #{join_table}
|
131
|
+
WHERE #{join_table}.#{foreign_key} IN (#{ list.map{ |e| e[klass.primary_key.to_sym].try(:to_s) }.compact.join(",") })
|
132
|
+
|
133
|
+
EOS
|
134
|
+
join_entries = ActiveRecord::Base.connection.execute(join_query).to_a
|
135
|
+
|
136
|
+
query = <<-EOS
|
137
|
+
SELECT
|
138
|
+
distinct #{association_klass.table_name}.*
|
139
|
+
FROM #{association_klass.table_name}
|
140
|
+
INNER JOIN #{join_table} ON #{join_table}.#{association_foreign_key} = #{association_klass.table_name}.#{association_klass.primary_key}
|
141
|
+
WHERE #{join_table}.#{foreign_key} IN (#{ list.map{ |e| e[klass.primary_key.to_sym].try(:to_s) }.compact.join(",") })
|
142
|
+
|
143
|
+
EOS
|
144
|
+
|
145
|
+
association_list = association_klass.find_by_sql(query).to_a
|
146
|
+
|
147
|
+
if inner_associations.is_a?(Array)
|
148
|
+
association_list.preload(*inner_associations)
|
149
|
+
else
|
150
|
+
association_list.preload(inner_associations)
|
151
|
+
end
|
152
|
+
|
153
|
+
list.each do |obj|
|
154
|
+
instance_variable_name = "@_#{association}".to_sym
|
155
|
+
|
156
|
+
association_key_list = join_entries.select{ |e| e[0] == obj[klass.primary_key.to_s] }.map(&:last)
|
157
|
+
|
158
|
+
association_list.select{ |e| association_key_list.include?( e[association_klass.primary_key.to_s] ) }.each do |association_obj|
|
159
|
+
each_list = obj.instance_variable_get(instance_variable_name)
|
160
|
+
each_list << association_obj
|
161
|
+
obj.instance_variable_set(instance_variable_name, each_list)
|
162
|
+
end
|
163
|
+
end
|
99
164
|
else
|
100
|
-
raise Ar::Preloader::Error.new("Unsupported
|
165
|
+
raise Ar::Preloader::Error.new("Unsupported association type: '#{association}'")
|
101
166
|
end
|
102
167
|
when Hash
|
103
168
|
association.each_pair do |k,v|
|
104
|
-
Ar::Preloader.preload_association(list, k,
|
169
|
+
Ar::Preloader.preload_association(list, k, v)
|
105
170
|
end
|
106
171
|
end
|
107
172
|
end
|
@@ -115,6 +180,7 @@ class Array
|
|
115
180
|
raise Ar::Preloader::Error.new("Cannot preload. Mixed type lists are not supported.") if (self.map(&:class).uniq.count > 1)
|
116
181
|
raise Ar::Preloader::Error.new("Cannot preload. At least one element in array is not an ActiveRecord object.") if (self.reject{|e| e.is_a?(ActiveRecord::Base) }.count > 0)
|
117
182
|
|
183
|
+
|
118
184
|
args.each do |arg|
|
119
185
|
raise Ar::Preloader::Error.new("Cannot find association '#{arg}' on one or more of the ActiveRecord objects.") if (self.reject{|e| Ar::Preloader.check_association_exists(e.class, arg) }.count > 0)
|
120
186
|
end
|
data/lib/ar/preloader/version.rb
CHANGED