bullet 8.1.3 → 8.3.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.
@@ -1,262 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bullet
4
- module ActiveRecord
5
- def self.enable
6
- require 'active_record'
7
- ::ActiveRecord::Base.class_eval do
8
- class << self
9
- alias_method :origin_find, :find
10
- def find(*args)
11
- result = origin_find(*args)
12
- if Bullet.start?
13
- if result.is_a? Array
14
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
15
- Bullet::Detector::CounterCache.add_possible_objects(result)
16
- elsif result.is_a? ::ActiveRecord::Base
17
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
18
- Bullet::Detector::CounterCache.add_impossible_object(result)
19
- end
20
- end
21
- result
22
- end
23
-
24
- alias_method :origin_find_by_sql, :find_by_sql
25
- def find_by_sql(sql, binds = [])
26
- result = origin_find_by_sql(sql, binds)
27
- if Bullet.start?
28
- if result.is_a? Array
29
- if result.size > 1
30
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
31
- Bullet::Detector::CounterCache.add_possible_objects(result)
32
- elsif result.size == 1
33
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
34
- Bullet::Detector::CounterCache.add_impossible_object(result.first)
35
- end
36
- elsif result.is_a? ::ActiveRecord::Base
37
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
38
- Bullet::Detector::CounterCache.add_impossible_object(result)
39
- end
40
- end
41
- result
42
- end
43
- end
44
- end
45
-
46
- ::ActiveRecord::Persistence.class_eval do
47
- def _create_record_with_bullet(*args)
48
- _create_record_without_bullet(*args).tap do
49
- Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
50
- Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
51
- end
52
- end
53
- alias_method_chain :_create_record, :bullet
54
- end
55
-
56
- ::ActiveRecord::Relation.class_eval do
57
- alias_method :origin_to_a, :to_a
58
-
59
- # if select a collection of objects, then these objects have possible to cause N+1 query.
60
- # if select only one object, then the only one object has impossible to cause N+1 query.
61
- def to_a
62
- records = origin_to_a
63
- if Bullet.start?
64
- if records.first.class.name !~ /^HABTM_/
65
- if records.size > 1
66
- Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
67
- Bullet::Detector::CounterCache.add_possible_objects(records)
68
- elsif records.size == 1
69
- Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
70
- Bullet::Detector::CounterCache.add_impossible_object(records.first)
71
- end
72
- end
73
- end
74
- records
75
- end
76
- end
77
-
78
- ::ActiveRecord::Associations::Preloader.class_eval do
79
- alias_method :origin_preloaders_on, :preloaders_on
80
-
81
- def preloaders_on(association, records, scope)
82
- if Bullet.start?
83
- records.compact!
84
- if records.first.class.name !~ /^HABTM_/
85
- records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
86
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
87
- end
88
- end
89
- origin_preloaders_on(association, records, scope)
90
- end
91
- end
92
-
93
- ::ActiveRecord::FinderMethods.class_eval do
94
- # add includes in scope
95
- alias_method :origin_find_with_associations, :find_with_associations
96
- def find_with_associations
97
- return origin_find_with_associations { |r| yield r } if block_given?
98
-
99
- records = origin_find_with_associations
100
- if Bullet.start?
101
- associations = (eager_load_values + includes_values).uniq
102
- records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
103
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
104
- end
105
- records
106
- end
107
- end
108
-
109
- ::ActiveRecord::Associations::JoinDependency.class_eval do
110
- alias_method :origin_instantiate, :instantiate
111
- alias_method :origin_construct, :construct
112
- alias_method :origin_construct_model, :construct_model
113
-
114
- def instantiate(result_set, aliases)
115
- @bullet_eager_loadings = {}
116
- records = origin_instantiate(result_set, aliases)
117
-
118
- if Bullet.start?
119
- @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
120
- objects = eager_loadings_hash.keys
121
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
122
- end
123
- end
124
- records
125
- end
126
-
127
- def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
128
- if Bullet.start?
129
- unless ar_parent.nil?
130
- parent.children.each do |node|
131
- key = aliases.column_alias(node, node.primary_key)
132
- id = row[key]
133
- next unless id.nil?
134
-
135
- associations = [node.reflection.name]
136
- if node.reflection.nested?
137
- associations << node.reflection.through_reflection.name
138
- end
139
- associations.each do |association|
140
- Bullet::Detector::Association.add_object_associations(ar_parent, association)
141
- Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
142
- @bullet_eager_loadings[ar_parent.class] ||= {}
143
- @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
144
- @bullet_eager_loadings[ar_parent.class][ar_parent] << association
145
- end
146
- end
147
- end
148
- end
149
-
150
- origin_construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
151
- end
152
-
153
- # call join associations
154
- def construct_model(record, node, row, model_cache, id, aliases)
155
- result = origin_construct_model(record, node, row, model_cache, id, aliases)
156
-
157
- if Bullet.start?
158
- associations = [node.reflection.name]
159
- if node.reflection.nested?
160
- associations << node.reflection.through_reflection.name
161
- end
162
- associations.each do |association|
163
- Bullet::Detector::Association.add_object_associations(record, association)
164
- Bullet::Detector::NPlusOneQuery.call_association(record, association)
165
- @bullet_eager_loadings[record.class] ||= {}
166
- @bullet_eager_loadings[record.class][record] ||= Set.new
167
- @bullet_eager_loadings[record.class][record] << association
168
- end
169
- end
170
-
171
- result
172
- end
173
- end
174
-
175
- ::ActiveRecord::Associations::CollectionAssociation.class_eval do
176
- # call one to many associations
177
- alias_method :origin_load_target, :load_target
178
- def load_target
179
- records = origin_load_target
180
-
181
- if Bullet.start?
182
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name, inversed: @inversed)
183
- if records.first.class.name !~ /^HABTM_/
184
- if records.size > 1
185
- Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
186
- Bullet::Detector::CounterCache.add_possible_objects(records)
187
- elsif records.size == 1
188
- Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
189
- Bullet::Detector::CounterCache.add_impossible_object(records.first)
190
- end
191
- end
192
- end
193
- records
194
- end
195
-
196
- alias_method :origin_empty?, :empty?
197
- def empty?
198
- if Bullet.start? && !has_cached_counter?(@reflection)
199
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
200
- end
201
- origin_empty?
202
- end
203
-
204
- alias_method :origin_include?, :include?
205
- def include?(object)
206
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
207
- origin_include?(object)
208
- end
209
- end
210
-
211
- ::ActiveRecord::Associations::SingularAssociation.class_eval do
212
- # call has_one and belongs_to associations
213
- alias_method :origin_reader, :reader
214
- def reader(force_reload = false)
215
- result = origin_reader(force_reload)
216
-
217
- if Bullet.start?
218
- if @owner.class.name !~ /^HABTM_/
219
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name, inversed: @inversed)
220
- unless @inversed
221
- if Bullet::Detector::NPlusOneQuery.impossible?(@owner)
222
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
223
- else
224
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
225
- end
226
- end
227
- end
228
- end
229
- result
230
- end
231
- end
232
-
233
- ::ActiveRecord::Associations::HasManyAssociation.class_eval do
234
- alias_method :origin_many_empty?, :empty?
235
- def empty?
236
- result = origin_many_empty?
237
- if Bullet.start? && !has_cached_counter?(@reflection)
238
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
239
- end
240
- result
241
- end
242
-
243
- alias_method :origin_count_records, :count_records
244
- def count_records
245
- result = has_cached_counter?
246
- Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name) if Bullet.start? && !result
247
- origin_count_records
248
- end
249
- end
250
-
251
- ::ActiveRecord::Associations::CollectionProxy.class_eval do
252
- def count(column_name = nil, options = {})
253
- if Bullet.start?
254
- Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
255
- Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
256
- end
257
- super(column_name, options)
258
- end
259
- end
260
- end
261
- end
262
- end
@@ -1,294 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bullet
4
- module SaveWithBulletSupport
5
- def _create_record(*)
6
- super do
7
- Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
8
- Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
9
- yield(self) if block_given?
10
- end
11
- end
12
- end
13
-
14
- module ActiveRecord
15
- def self.enable
16
- require 'active_record'
17
- ::ActiveRecord::Base.extend(
18
- Module.new do
19
- def find_by_sql(sql, binds = [], preparable: nil, &block)
20
- result = super
21
- if Bullet.start?
22
- if result.is_a? Array
23
- if result.size > 1
24
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
25
- Bullet::Detector::CounterCache.add_possible_objects(result)
26
- elsif result.size == 1
27
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
28
- Bullet::Detector::CounterCache.add_impossible_object(result.first)
29
- end
30
- elsif result.is_a? ::ActiveRecord::Base
31
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
32
- Bullet::Detector::CounterCache.add_impossible_object(result)
33
- end
34
- end
35
- result
36
- end
37
- end
38
- )
39
-
40
- ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
41
-
42
- ::ActiveRecord::Relation.prepend(
43
- Module.new do
44
- # if select a collection of objects, then these objects have possible to cause N+1 query.
45
- # if select only one object, then the only one object has impossible to cause N+1 query.
46
- def records
47
- result = super
48
- if Bullet.start?
49
- if result.first.class.name !~ /^HABTM_/
50
- if result.size > 1
51
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
52
- Bullet::Detector::CounterCache.add_possible_objects(result)
53
- elsif result.size == 1
54
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
55
- Bullet::Detector::CounterCache.add_impossible_object(result.first)
56
- end
57
- end
58
- end
59
- result
60
- end
61
- end
62
- )
63
-
64
- ::ActiveRecord::Associations::Preloader.prepend(
65
- Module.new do
66
- def preloaders_for_one(association, records, scope)
67
- if Bullet.start?
68
- records.compact!
69
- if records.first.class.name !~ /^HABTM_/
70
- records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
71
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
72
- end
73
- end
74
- super
75
- end
76
- end
77
- )
78
-
79
- ::ActiveRecord::FinderMethods.prepend(
80
- Module.new do
81
- # add includes in scope
82
- def find_with_associations
83
- return super { |r| yield r } if block_given?
84
-
85
- records = super
86
- if Bullet.start?
87
- associations = (eager_load_values + includes_values).uniq
88
- records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
89
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
90
- end
91
- records
92
- end
93
- end
94
- )
95
-
96
- ::ActiveRecord::Associations::JoinDependency.prepend(
97
- Module.new do
98
- if ::ActiveRecord::Associations::JoinDependency.instance_method(:instantiate).parameters.last[0] == :block
99
- # ActiveRecord >= 5.1.5
100
- def instantiate(result_set, &block)
101
- @bullet_eager_loadings = {}
102
- records = super
103
-
104
- if Bullet.start?
105
- @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
106
- objects = eager_loadings_hash.keys
107
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
108
- objects,
109
- eager_loadings_hash[objects.first].to_a
110
- )
111
- end
112
- end
113
- records
114
- end
115
- else
116
- # ActiveRecord <= 5.1.4
117
- def instantiate(result_set, aliases)
118
- @bullet_eager_loadings = {}
119
- records = super
120
-
121
- if Bullet.start?
122
- @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
123
- objects = eager_loadings_hash.keys
124
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
125
- objects,
126
- eager_loadings_hash[objects.first].to_a
127
- )
128
- end
129
- end
130
- records
131
- end
132
- end
133
-
134
- def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
135
- if Bullet.start?
136
- unless ar_parent.nil?
137
- parent.children.each do |node|
138
- key = aliases.column_alias(node, node.primary_key)
139
- id = row[key]
140
- next unless id.nil?
141
-
142
- associations = [node.reflection.name]
143
- if node.reflection.through_reflection?
144
- associations << node.reflection.through_reflection.name
145
- end
146
- associations.each do |association|
147
- Bullet::Detector::Association.add_object_associations(ar_parent, association)
148
- Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
149
- @bullet_eager_loadings[ar_parent.class] ||= {}
150
- @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
151
- @bullet_eager_loadings[ar_parent.class][ar_parent] << association
152
- end
153
- end
154
- end
155
- end
156
-
157
- super
158
- end
159
-
160
- # call join associations
161
- def construct_model(record, node, row, model_cache, id, aliases)
162
- result = super
163
-
164
- if Bullet.start?
165
- associations = [node.reflection.name]
166
- if node.reflection.through_reflection?
167
- associations << node.reflection.through_reflection.name
168
- end
169
- associations.each do |association|
170
- Bullet::Detector::Association.add_object_associations(record, association)
171
- Bullet::Detector::NPlusOneQuery.call_association(record, association)
172
- @bullet_eager_loadings[record.class] ||= {}
173
- @bullet_eager_loadings[record.class][record] ||= Set.new
174
- @bullet_eager_loadings[record.class][record] << association
175
- end
176
- end
177
-
178
- result
179
- end
180
- end
181
- )
182
-
183
- ::ActiveRecord::Associations::CollectionAssociation.prepend(
184
- Module.new do
185
- def load_target
186
- records = super
187
-
188
- if Bullet.start?
189
- if is_a? ::ActiveRecord::Associations::ThroughAssociation
190
- refl = reflection.through_reflection
191
- association = owner.association(refl.name)
192
- if association.loaded?
193
- Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
194
- Array.wrap(association.target).each do |through_record|
195
- Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
196
- end
197
-
198
- if refl.through_reflection?
199
- refl = refl.through_reflection while refl.through_reflection?
200
-
201
- Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
202
- end
203
- end
204
- end
205
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, inversed: @inversed)
206
- if records.first.class.name !~ /^HABTM_/
207
- if records.size > 1
208
- Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
209
- Bullet::Detector::CounterCache.add_possible_objects(records)
210
- elsif records.size == 1
211
- Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
212
- Bullet::Detector::CounterCache.add_impossible_object(records.first)
213
- end
214
- end
215
- end
216
- records
217
- end
218
-
219
- def empty?
220
- if Bullet.start? && !reflection.has_cached_counter?
221
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
222
- end
223
- super
224
- end
225
-
226
- def include?(object)
227
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
228
- super
229
- end
230
- end
231
- )
232
-
233
- ::ActiveRecord::Associations::SingularAssociation.prepend(
234
- Module.new do
235
- # call has_one and belongs_to associations
236
- def target
237
- result = super()
238
-
239
- if Bullet.start?
240
- if owner.class.name !~ /^HABTM_/
241
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, inversed: @inversed)
242
- unless @inversed
243
- if Bullet::Detector::NPlusOneQuery.impossible?(owner)
244
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
245
- else
246
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
247
- end
248
- end
249
- end
250
- end
251
- result
252
- end
253
- end
254
- )
255
-
256
- ::ActiveRecord::Associations::HasManyAssociation.prepend(
257
- Module.new do
258
- def empty?
259
- if Bullet.start? && !reflection.has_cached_counter?
260
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
261
- end
262
- super
263
- end
264
-
265
- def count_records
266
- result = reflection.has_cached_counter?
267
- if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
268
- Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
269
- end
270
- super
271
- end
272
- end
273
- )
274
-
275
- ::ActiveRecord::Associations::CollectionProxy.prepend(
276
- Module.new do
277
- def count(column_name = nil)
278
- if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
279
- Bullet::Detector::CounterCache.add_counter_cache(
280
- proxy_association.owner,
281
- proxy_association.reflection.name
282
- )
283
- Bullet::Detector::NPlusOneQuery.call_association(
284
- proxy_association.owner,
285
- proxy_association.reflection.name
286
- )
287
- end
288
- super(column_name)
289
- end
290
- end
291
- )
292
- end
293
- end
294
- end