bullet 7.1.6 → 8.0.1
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/CHANGELOG.md +19 -0
- data/MIT-LICENSE +1 -1
- data/README.md +2 -2
- data/lib/bullet/active_record5.rb +2 -2
- data/lib/bullet/active_record60.rb +2 -2
- data/lib/bullet/active_record72.rb +318 -0
- data/lib/bullet/active_record80.rb +318 -0
- data/lib/bullet/dependency.rb +16 -0
- data/lib/bullet/detector/association.rb +10 -8
- data/lib/bullet/detector/counter_cache.rb +4 -2
- data/lib/bullet/detector/n_plus_one_query.rb +8 -5
- data/lib/bullet/detector/unused_eager_loading.rb +3 -0
- data/lib/bullet/ext/object.rb +24 -20
- data/lib/bullet/ext/string.rb +10 -3
- data/lib/bullet/registry/call_stack.rb +1 -1
- data/lib/bullet/registry/object.rb +3 -0
- data/lib/bullet/stack_trace_filter.rb +4 -4
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +30 -24
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb8c8d2264141849784cb8a103b9521a8fad5ba11eba1daa9a5a576f02c2bcc6
|
4
|
+
data.tar.gz: e9b5a2a2f123ad3e84007407123103535844dcde3c7e9f3da304eb019d55f96d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc9c11edab1b705ba7f51f63bf0315c94d5c3f4178684c42da4042adeef52da7570939a91556301dcb076a08a9dc816b89cd38c8a5399c7a8fe81baf2562ca01
|
7
|
+
data.tar.gz: aa0cc8a93443e8fa17582ac89dca1eba8714080ebab2d0199b0a298f77ccf3f0a019b457615e18e6dd8827f3573e0fe657d9ada3c36d6e8cd588e2b2c4a4090f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
## Next Release
|
2
2
|
|
3
|
+
## 8.0.1 (02/10/2025)
|
4
|
+
|
5
|
+
* Update benchmark to use sqlite
|
6
|
+
* Reduce mem allocations
|
7
|
+
* Require active_support's inflections module before requiring the delegation module
|
8
|
+
|
9
|
+
## 8.0.0 (11/10/2024)
|
10
|
+
|
11
|
+
* Support Rails 8
|
12
|
+
* Drop Rails 4.0 and 4.1 support
|
13
|
+
* Require Ruby at least 2.7.0
|
14
|
+
* Store global objects into thread-local variables
|
15
|
+
* Avoid globally polluting `::String` and `::Object` classes
|
16
|
+
|
17
|
+
## 7.2.0 (07/12/2024)
|
18
|
+
|
19
|
+
* Support Rails 7.2
|
20
|
+
* Fix count method signature for active_record5 and active_record60
|
21
|
+
|
3
22
|
## 7.1.6 (01/16/2024)
|
4
23
|
|
5
24
|
* Allow apps to not include the user in a notification
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|

|
4
4
|
[](http://badge.fury.io/rb/bullet)
|
5
5
|
[](https://awesomecode.io/repos/flyerhzm/bullet)
|
6
|
-
[](https://coderwall.com/flyerhzm)
|
7
7
|
|
8
8
|
The Bullet gem is designed to help you increase your application's performance by reducing the number of queries it makes. It will watch your queries while you develop your application and notify you when you should add eager loading (N+1 queries), when you're using eager loading that isn't necessary and when you should use counter cache.
|
9
9
|
|
@@ -20,7 +20,7 @@ If you use activerecord 3.x, please use bullet < 5.5.0
|
|
20
20
|
* [http://railscasts.com/episodes/372-bullet](http://railscasts.com/episodes/372-bullet)
|
21
21
|
* [http://ruby5.envylabs.com/episodes/9-episode-8-september-8-2009](http://ruby5.envylabs.com/episodes/9-episode-8-september-8-2009)
|
22
22
|
* [http://railslab.newrelic.com/2009/10/23/episode-19-on-the-edge-part-1](http://railslab.newrelic.com/2009/10/23/episode-19-on-the-edge-part-1)
|
23
|
-
* [
|
23
|
+
* [https://rubyonrails.org/2009/10/22/community-highlights](https://rubyonrails.org/2009/10/22/community-highlights)
|
24
24
|
|
25
25
|
## Install
|
26
26
|
|
@@ -273,7 +273,7 @@ module Bullet
|
|
273
273
|
|
274
274
|
::ActiveRecord::Associations::CollectionProxy.prepend(
|
275
275
|
Module.new do
|
276
|
-
def count
|
276
|
+
def count(column_name = nil)
|
277
277
|
if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
278
278
|
Bullet::Detector::CounterCache.add_counter_cache(
|
279
279
|
proxy_association.owner,
|
@@ -284,7 +284,7 @@ module Bullet
|
|
284
284
|
proxy_association.reflection.name
|
285
285
|
)
|
286
286
|
end
|
287
|
-
super
|
287
|
+
super(column_name)
|
288
288
|
end
|
289
289
|
end
|
290
290
|
)
|
@@ -282,7 +282,7 @@ module Bullet
|
|
282
282
|
|
283
283
|
::ActiveRecord::Associations::CollectionProxy.prepend(
|
284
284
|
Module.new do
|
285
|
-
def count
|
285
|
+
def count(column_name = nil)
|
286
286
|
if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
287
287
|
Bullet::Detector::CounterCache.add_counter_cache(
|
288
288
|
proxy_association.owner,
|
@@ -293,7 +293,7 @@ module Bullet
|
|
293
293
|
proxy_association.reflection.name
|
294
294
|
)
|
295
295
|
end
|
296
|
-
super
|
296
|
+
super(column_name)
|
297
297
|
end
|
298
298
|
end
|
299
299
|
)
|
@@ -0,0 +1,318 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bullet
|
4
|
+
module SaveWithBulletSupport
|
5
|
+
def _create_record(*)
|
6
|
+
super do
|
7
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
8
|
+
yield(self) if block_given?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ActiveRecord
|
14
|
+
def self.enable
|
15
|
+
require 'active_record'
|
16
|
+
::ActiveRecord::Base.extend(
|
17
|
+
Module.new do
|
18
|
+
def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
|
19
|
+
result = super
|
20
|
+
if Bullet.start?
|
21
|
+
if result.is_a? Array
|
22
|
+
if result.size > 1
|
23
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
24
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
25
|
+
elsif result.size == 1
|
26
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
27
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
28
|
+
end
|
29
|
+
elsif result.is_a? ::ActiveRecord::Base
|
30
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
|
31
|
+
Bullet::Detector::CounterCache.add_impossible_object(result)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
)
|
38
|
+
|
39
|
+
::ActiveRecord::Base.prepend(SaveWithBulletSupport)
|
40
|
+
|
41
|
+
::ActiveRecord::Relation.prepend(
|
42
|
+
Module.new do
|
43
|
+
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
44
|
+
# if select only one object, then the only one object has impossible to cause N+1 query.
|
45
|
+
def records
|
46
|
+
result = super
|
47
|
+
if Bullet.start?
|
48
|
+
if result.first.class.name !~ /^HABTM_/
|
49
|
+
if result.size > 1
|
50
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
51
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
52
|
+
elsif result.size == 1
|
53
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
54
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
result
|
59
|
+
end
|
60
|
+
end
|
61
|
+
)
|
62
|
+
|
63
|
+
::ActiveRecord::Associations::Preloader::Batch.prepend(
|
64
|
+
Module.new do
|
65
|
+
def call
|
66
|
+
if Bullet.start?
|
67
|
+
@preloaders.each do |preloader|
|
68
|
+
preloader.records.each { |record|
|
69
|
+
Bullet::Detector::Association.add_object_associations(record, preloader.associations)
|
70
|
+
}
|
71
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
super
|
75
|
+
end
|
76
|
+
end
|
77
|
+
)
|
78
|
+
|
79
|
+
::ActiveRecord::Associations::Preloader::Branch.prepend(
|
80
|
+
Module.new do
|
81
|
+
def preloaders_for_reflection(reflection, reflection_records)
|
82
|
+
if Bullet.start?
|
83
|
+
reflection_records.compact!
|
84
|
+
if reflection_records.first.class.name !~ /^HABTM_/
|
85
|
+
reflection_records.each { |record|
|
86
|
+
Bullet::Detector::Association.add_object_associations(record, reflection.name)
|
87
|
+
}
|
88
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
94
|
+
)
|
95
|
+
|
96
|
+
::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
|
97
|
+
Module.new do
|
98
|
+
def source_preloaders
|
99
|
+
if Bullet.start? && !defined?(@source_preloaders)
|
100
|
+
preloaders = super
|
101
|
+
preloaders.each do |preloader|
|
102
|
+
reflection_name = preloader.send(:reflection).name
|
103
|
+
preloader.send(:owners).each do |owner|
|
104
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
else
|
108
|
+
super
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
)
|
113
|
+
|
114
|
+
::ActiveRecord::Associations::JoinDependency.prepend(
|
115
|
+
Module.new do
|
116
|
+
def instantiate(result_set, strict_loading_value, &block)
|
117
|
+
@bullet_eager_loadings = {}
|
118
|
+
records = super
|
119
|
+
|
120
|
+
if Bullet.start?
|
121
|
+
@bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
|
122
|
+
objects = eager_loadings_hash.keys
|
123
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
|
124
|
+
objects,
|
125
|
+
eager_loadings_hash[objects.first].to_a
|
126
|
+
)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
records
|
130
|
+
end
|
131
|
+
|
132
|
+
def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
|
133
|
+
if Bullet.start?
|
134
|
+
unless ar_parent.nil?
|
135
|
+
parent.children.each do |node|
|
136
|
+
key = aliases.column_alias(node, node.primary_key)
|
137
|
+
id = row[key]
|
138
|
+
next unless id.nil?
|
139
|
+
|
140
|
+
associations = [node.reflection.name]
|
141
|
+
if node.reflection.through_reflection?
|
142
|
+
associations << node.reflection.through_reflection.name
|
143
|
+
end
|
144
|
+
associations.each do |association|
|
145
|
+
Bullet::Detector::Association.add_object_associations(ar_parent, association)
|
146
|
+
Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
|
147
|
+
@bullet_eager_loadings[ar_parent.class] ||= {}
|
148
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
|
149
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] << association
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
super
|
156
|
+
end
|
157
|
+
|
158
|
+
# call join associations
|
159
|
+
def construct_model(record, node, row, model_cache, id, strict_loading_value)
|
160
|
+
result = super
|
161
|
+
|
162
|
+
if Bullet.start?
|
163
|
+
associations = [node.reflection.name]
|
164
|
+
if node.reflection.through_reflection?
|
165
|
+
associations << node.reflection.through_reflection.name
|
166
|
+
end
|
167
|
+
associations.each do |association|
|
168
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
169
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, association)
|
170
|
+
@bullet_eager_loadings[record.class] ||= {}
|
171
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
172
|
+
@bullet_eager_loadings[record.class][record] << association
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
result
|
177
|
+
end
|
178
|
+
end
|
179
|
+
)
|
180
|
+
|
181
|
+
::ActiveRecord::Associations::Association.prepend(
|
182
|
+
Module.new do
|
183
|
+
def inversed_from(record)
|
184
|
+
if Bullet.start?
|
185
|
+
Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
|
186
|
+
end
|
187
|
+
super
|
188
|
+
end
|
189
|
+
|
190
|
+
def inversed_from_queries(record)
|
191
|
+
if Bullet.start? && inversable?(record)
|
192
|
+
Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
|
193
|
+
end
|
194
|
+
super
|
195
|
+
end
|
196
|
+
end
|
197
|
+
)
|
198
|
+
|
199
|
+
::ActiveRecord::Associations::CollectionAssociation.prepend(
|
200
|
+
Module.new do
|
201
|
+
def load_target
|
202
|
+
records = super
|
203
|
+
|
204
|
+
if Bullet.start?
|
205
|
+
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
206
|
+
association = owner.association(reflection.through_reflection.name)
|
207
|
+
if association.loaded?
|
208
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
|
209
|
+
Array.wrap(association.target).each do |through_record|
|
210
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
211
|
+
end
|
212
|
+
|
213
|
+
if reflection.through_reflection != through_reflection
|
214
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
219
|
+
if records.first.class.name !~ /^HABTM_/
|
220
|
+
if records.size > 1
|
221
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
222
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
223
|
+
elsif records.size == 1
|
224
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
225
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
records
|
230
|
+
end
|
231
|
+
|
232
|
+
def empty?
|
233
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
234
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
235
|
+
end
|
236
|
+
super
|
237
|
+
end
|
238
|
+
|
239
|
+
def include?(object)
|
240
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
|
241
|
+
super
|
242
|
+
end
|
243
|
+
end
|
244
|
+
)
|
245
|
+
|
246
|
+
::ActiveRecord::Associations::SingularAssociation.prepend(
|
247
|
+
Module.new do
|
248
|
+
# call has_one and belongs_to associations
|
249
|
+
def reader
|
250
|
+
result = super
|
251
|
+
|
252
|
+
if Bullet.start?
|
253
|
+
if owner.class.name !~ /^HABTM_/
|
254
|
+
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
255
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
|
256
|
+
association = owner.association(reflection.through_reflection.name)
|
257
|
+
Array.wrap(association.target).each do |through_record|
|
258
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
259
|
+
end
|
260
|
+
|
261
|
+
if reflection.through_reflection != through_reflection
|
262
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
266
|
+
|
267
|
+
if Bullet::Detector::NPlusOneQuery.impossible?(owner)
|
268
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
269
|
+
else
|
270
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
result
|
275
|
+
end
|
276
|
+
end
|
277
|
+
)
|
278
|
+
|
279
|
+
::ActiveRecord::Associations::HasManyAssociation.prepend(
|
280
|
+
Module.new do
|
281
|
+
def empty?
|
282
|
+
result = super
|
283
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
284
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
285
|
+
end
|
286
|
+
result
|
287
|
+
end
|
288
|
+
|
289
|
+
def count_records
|
290
|
+
result = reflection.has_cached_counter?
|
291
|
+
if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
292
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
293
|
+
end
|
294
|
+
super
|
295
|
+
end
|
296
|
+
end
|
297
|
+
)
|
298
|
+
|
299
|
+
::ActiveRecord::Associations::CollectionProxy.prepend(
|
300
|
+
Module.new do
|
301
|
+
def count(column_name = nil)
|
302
|
+
if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
303
|
+
Bullet::Detector::CounterCache.add_counter_cache(
|
304
|
+
proxy_association.owner,
|
305
|
+
proxy_association.reflection.name
|
306
|
+
)
|
307
|
+
Bullet::Detector::NPlusOneQuery.call_association(
|
308
|
+
proxy_association.owner,
|
309
|
+
proxy_association.reflection.name
|
310
|
+
)
|
311
|
+
end
|
312
|
+
super(column_name)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
@@ -0,0 +1,318 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bullet
|
4
|
+
module SaveWithBulletSupport
|
5
|
+
def _create_record(*)
|
6
|
+
super do
|
7
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
8
|
+
yield(self) if block_given?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ActiveRecord
|
14
|
+
def self.enable
|
15
|
+
require 'active_record'
|
16
|
+
::ActiveRecord::Base.extend(
|
17
|
+
Module.new do
|
18
|
+
def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
|
19
|
+
result = super
|
20
|
+
if Bullet.start?
|
21
|
+
if result.is_a? Array
|
22
|
+
if result.size > 1
|
23
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
24
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
25
|
+
elsif result.size == 1
|
26
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
27
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
28
|
+
end
|
29
|
+
elsif result.is_a? ::ActiveRecord::Base
|
30
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
|
31
|
+
Bullet::Detector::CounterCache.add_impossible_object(result)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
)
|
38
|
+
|
39
|
+
::ActiveRecord::Base.prepend(SaveWithBulletSupport)
|
40
|
+
|
41
|
+
::ActiveRecord::Relation.prepend(
|
42
|
+
Module.new do
|
43
|
+
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
44
|
+
# if select only one object, then the only one object has impossible to cause N+1 query.
|
45
|
+
def records
|
46
|
+
result = super
|
47
|
+
if Bullet.start?
|
48
|
+
if result.first.class.name !~ /^HABTM_/
|
49
|
+
if result.size > 1
|
50
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
51
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
52
|
+
elsif result.size == 1
|
53
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
54
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
result
|
59
|
+
end
|
60
|
+
end
|
61
|
+
)
|
62
|
+
|
63
|
+
::ActiveRecord::Associations::Preloader::Batch.prepend(
|
64
|
+
Module.new do
|
65
|
+
def call
|
66
|
+
if Bullet.start?
|
67
|
+
@preloaders.each do |preloader|
|
68
|
+
preloader.records.each { |record|
|
69
|
+
Bullet::Detector::Association.add_object_associations(record, preloader.associations)
|
70
|
+
}
|
71
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
super
|
75
|
+
end
|
76
|
+
end
|
77
|
+
)
|
78
|
+
|
79
|
+
::ActiveRecord::Associations::Preloader::Branch.prepend(
|
80
|
+
Module.new do
|
81
|
+
def preloaders_for_reflection(reflection, reflection_records)
|
82
|
+
if Bullet.start?
|
83
|
+
reflection_records.compact!
|
84
|
+
if reflection_records.first.class.name !~ /^HABTM_/
|
85
|
+
reflection_records.each { |record|
|
86
|
+
Bullet::Detector::Association.add_object_associations(record, reflection.name)
|
87
|
+
}
|
88
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
94
|
+
)
|
95
|
+
|
96
|
+
::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
|
97
|
+
Module.new do
|
98
|
+
def source_preloaders
|
99
|
+
if Bullet.start? && !defined?(@source_preloaders)
|
100
|
+
preloaders = super
|
101
|
+
preloaders.each do |preloader|
|
102
|
+
reflection_name = preloader.send(:reflection).name
|
103
|
+
preloader.send(:owners).each do |owner|
|
104
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
else
|
108
|
+
super
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
)
|
113
|
+
|
114
|
+
::ActiveRecord::Associations::JoinDependency.prepend(
|
115
|
+
Module.new do
|
116
|
+
def instantiate(result_set, strict_loading_value, &block)
|
117
|
+
@bullet_eager_loadings = {}
|
118
|
+
records = super
|
119
|
+
|
120
|
+
if Bullet.start?
|
121
|
+
@bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
|
122
|
+
objects = eager_loadings_hash.keys
|
123
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
|
124
|
+
objects,
|
125
|
+
eager_loadings_hash[objects.first].to_a
|
126
|
+
)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
records
|
130
|
+
end
|
131
|
+
|
132
|
+
def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
|
133
|
+
if Bullet.start?
|
134
|
+
unless ar_parent.nil?
|
135
|
+
parent.children.each do |node|
|
136
|
+
key = aliases.column_alias(node, node.primary_key)
|
137
|
+
id = row[key]
|
138
|
+
next unless id.nil?
|
139
|
+
|
140
|
+
associations = [node.reflection.name]
|
141
|
+
if node.reflection.through_reflection?
|
142
|
+
associations << node.reflection.through_reflection.name
|
143
|
+
end
|
144
|
+
associations.each do |association|
|
145
|
+
Bullet::Detector::Association.add_object_associations(ar_parent, association)
|
146
|
+
Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
|
147
|
+
@bullet_eager_loadings[ar_parent.class] ||= {}
|
148
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
|
149
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] << association
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
super
|
156
|
+
end
|
157
|
+
|
158
|
+
# call join associations
|
159
|
+
def construct_model(record, node, row, model_cache, id, strict_loading_value)
|
160
|
+
result = super
|
161
|
+
|
162
|
+
if Bullet.start?
|
163
|
+
associations = [node.reflection.name]
|
164
|
+
if node.reflection.through_reflection?
|
165
|
+
associations << node.reflection.through_reflection.name
|
166
|
+
end
|
167
|
+
associations.each do |association|
|
168
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
169
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, association)
|
170
|
+
@bullet_eager_loadings[record.class] ||= {}
|
171
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
172
|
+
@bullet_eager_loadings[record.class][record] << association
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
result
|
177
|
+
end
|
178
|
+
end
|
179
|
+
)
|
180
|
+
|
181
|
+
::ActiveRecord::Associations::Association.prepend(
|
182
|
+
Module.new do
|
183
|
+
def inversed_from(record)
|
184
|
+
if Bullet.start?
|
185
|
+
Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
|
186
|
+
end
|
187
|
+
super
|
188
|
+
end
|
189
|
+
|
190
|
+
def inversed_from_queries(record)
|
191
|
+
if Bullet.start? && inversable?(record)
|
192
|
+
Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
|
193
|
+
end
|
194
|
+
super
|
195
|
+
end
|
196
|
+
end
|
197
|
+
)
|
198
|
+
|
199
|
+
::ActiveRecord::Associations::CollectionAssociation.prepend(
|
200
|
+
Module.new do
|
201
|
+
def load_target
|
202
|
+
records = super
|
203
|
+
|
204
|
+
if Bullet.start?
|
205
|
+
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
206
|
+
association = owner.association(reflection.through_reflection.name)
|
207
|
+
if association.loaded?
|
208
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
|
209
|
+
Array.wrap(association.target).each do |through_record|
|
210
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
211
|
+
end
|
212
|
+
|
213
|
+
if reflection.through_reflection != through_reflection
|
214
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
219
|
+
if records.first.class.name !~ /^HABTM_/
|
220
|
+
if records.size > 1
|
221
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
222
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
223
|
+
elsif records.size == 1
|
224
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
225
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
records
|
230
|
+
end
|
231
|
+
|
232
|
+
def empty?
|
233
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
234
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
235
|
+
end
|
236
|
+
super
|
237
|
+
end
|
238
|
+
|
239
|
+
def include?(object)
|
240
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
|
241
|
+
super
|
242
|
+
end
|
243
|
+
end
|
244
|
+
)
|
245
|
+
|
246
|
+
::ActiveRecord::Associations::SingularAssociation.prepend(
|
247
|
+
Module.new do
|
248
|
+
# call has_one and belongs_to associations
|
249
|
+
def reader
|
250
|
+
result = super
|
251
|
+
|
252
|
+
if Bullet.start?
|
253
|
+
if owner.class.name !~ /^HABTM_/
|
254
|
+
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
255
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
|
256
|
+
association = owner.association(reflection.through_reflection.name)
|
257
|
+
Array.wrap(association.target).each do |through_record|
|
258
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
259
|
+
end
|
260
|
+
|
261
|
+
if reflection.through_reflection != through_reflection
|
262
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
266
|
+
|
267
|
+
if Bullet::Detector::NPlusOneQuery.impossible?(owner)
|
268
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
269
|
+
else
|
270
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
result
|
275
|
+
end
|
276
|
+
end
|
277
|
+
)
|
278
|
+
|
279
|
+
::ActiveRecord::Associations::HasManyAssociation.prepend(
|
280
|
+
Module.new do
|
281
|
+
def empty?
|
282
|
+
result = super
|
283
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
284
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
285
|
+
end
|
286
|
+
result
|
287
|
+
end
|
288
|
+
|
289
|
+
def count_records
|
290
|
+
result = reflection.has_cached_counter?
|
291
|
+
if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
292
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
293
|
+
end
|
294
|
+
super
|
295
|
+
end
|
296
|
+
end
|
297
|
+
)
|
298
|
+
|
299
|
+
::ActiveRecord::Associations::CollectionProxy.prepend(
|
300
|
+
Module.new do
|
301
|
+
def count(column_name = nil)
|
302
|
+
if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
303
|
+
Bullet::Detector::CounterCache.add_counter_cache(
|
304
|
+
proxy_association.owner,
|
305
|
+
proxy_association.reflection.name
|
306
|
+
)
|
307
|
+
Bullet::Detector::NPlusOneQuery.call_association(
|
308
|
+
proxy_association.owner,
|
309
|
+
proxy_association.reflection.name
|
310
|
+
)
|
311
|
+
end
|
312
|
+
super(column_name)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
data/lib/bullet/dependency.rb
CHANGED
@@ -33,6 +33,10 @@ module Bullet
|
|
33
33
|
'active_record70'
|
34
34
|
elsif active_record71?
|
35
35
|
'active_record71'
|
36
|
+
elsif active_record72?
|
37
|
+
'active_record72'
|
38
|
+
elsif active_record80?
|
39
|
+
'active_record80'
|
36
40
|
else
|
37
41
|
raise "Bullet does not support active_record #{::ActiveRecord::VERSION::STRING} yet"
|
38
42
|
end
|
@@ -74,6 +78,10 @@ module Bullet
|
|
74
78
|
active_record? && ::ActiveRecord::VERSION::MAJOR == 7
|
75
79
|
end
|
76
80
|
|
81
|
+
def active_record8?
|
82
|
+
active_record? && ::ActiveRecord::VERSION::MAJOR == 8
|
83
|
+
end
|
84
|
+
|
77
85
|
def active_record40?
|
78
86
|
active_record4? && ::ActiveRecord::VERSION::MINOR == 0
|
79
87
|
end
|
@@ -114,6 +122,14 @@ module Bullet
|
|
114
122
|
active_record7? && ::ActiveRecord::VERSION::MINOR == 1
|
115
123
|
end
|
116
124
|
|
125
|
+
def active_record72?
|
126
|
+
active_record7? && ::ActiveRecord::VERSION::MINOR == 2
|
127
|
+
end
|
128
|
+
|
129
|
+
def active_record80?
|
130
|
+
active_record8? && ::ActiveRecord::VERSION::MINOR == 0
|
131
|
+
end
|
132
|
+
|
117
133
|
def mongoid4x?
|
118
134
|
mongoid? && ::Mongoid::VERSION =~ /\A4/
|
119
135
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
using Bullet::Ext::Object
|
4
|
+
|
3
5
|
module Bullet
|
4
6
|
module Detector
|
5
7
|
class Association < Base
|
@@ -34,7 +36,7 @@ module Bullet
|
|
34
36
|
# that the objects may cause N+1 query.
|
35
37
|
# e.g. { Post => ["Post:1", "Post:2"] }
|
36
38
|
def possible_objects
|
37
|
-
Thread.current
|
39
|
+
Thread.current.thread_variable_get(:bullet_possible_objects)
|
38
40
|
end
|
39
41
|
|
40
42
|
# impossible_objects keep the class to objects relationships
|
@@ -43,7 +45,7 @@ module Bullet
|
|
43
45
|
# if find collection returns only one object, then the object is impossible object,
|
44
46
|
# impossible_objects are used to avoid treating 1+1 query to N+1 query.
|
45
47
|
def impossible_objects
|
46
|
-
Thread.current
|
48
|
+
Thread.current.thread_variable_get(:bullet_impossible_objects)
|
47
49
|
end
|
48
50
|
|
49
51
|
private
|
@@ -54,7 +56,7 @@ module Bullet
|
|
54
56
|
# the object_associations keep all associations that may be or may no be
|
55
57
|
# unpreload associations or unused preload associations.
|
56
58
|
def object_associations
|
57
|
-
Thread.current
|
59
|
+
Thread.current.thread_variable_get(:bullet_object_associations)
|
58
60
|
end
|
59
61
|
|
60
62
|
# call_object_associations keep the object relationships
|
@@ -62,27 +64,27 @@ module Bullet
|
|
62
64
|
# e.g. { "Post:1" => [:comments] }
|
63
65
|
# they are used to detect unused preload associations.
|
64
66
|
def call_object_associations
|
65
|
-
Thread.current
|
67
|
+
Thread.current.thread_variable_get(:bullet_call_object_associations)
|
66
68
|
end
|
67
69
|
|
68
70
|
# inversed_objects keeps object relationships
|
69
71
|
# that association is inversed.
|
70
72
|
# e.g. { "Comment:1" => ["post"] }
|
71
73
|
def inversed_objects
|
72
|
-
Thread.current
|
74
|
+
Thread.current.thread_variable_get(:bullet_inversed_objects)
|
73
75
|
end
|
74
76
|
|
75
77
|
# eager_loadings keep the object relationships
|
76
78
|
# that the associations are preloaded by find :include.
|
77
79
|
# e.g. { ["Post:1", "Post:2"] => [:comments, :user] }
|
78
80
|
def eager_loadings
|
79
|
-
Thread.current
|
81
|
+
Thread.current.thread_variable_get(:bullet_eager_loadings)
|
80
82
|
end
|
81
83
|
|
82
|
-
#
|
84
|
+
# call_stacks keeps stacktraces where querie-objects were called from.
|
83
85
|
# e.g. { 'Object:111' => [SomeProject/app/controllers/...] }
|
84
86
|
def call_stacks
|
85
|
-
Thread.current
|
87
|
+
Thread.current.thread_variable_get(:bullet_call_stacks)
|
86
88
|
end
|
87
89
|
end
|
88
90
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
using Bullet::Ext::Object
|
4
|
+
|
3
5
|
module Bullet
|
4
6
|
module Detector
|
5
7
|
class CounterCache < Base
|
@@ -44,11 +46,11 @@ module Bullet
|
|
44
46
|
end
|
45
47
|
|
46
48
|
def possible_objects
|
47
|
-
Thread.current
|
49
|
+
Thread.current.thread_variable_get(:bullet_counter_possible_objects)
|
48
50
|
end
|
49
51
|
|
50
52
|
def impossible_objects
|
51
|
-
Thread.current
|
53
|
+
Thread.current.thread_variable_get(:bullet_counter_impossible_objects)
|
52
54
|
end
|
53
55
|
|
54
56
|
private
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
using Bullet::Ext::Object
|
4
|
+
|
3
5
|
module Bullet
|
4
6
|
module Detector
|
5
7
|
class NPlusOneQuery < Association
|
@@ -25,7 +27,7 @@ module Bullet
|
|
25
27
|
)
|
26
28
|
if !excluded_stacktrace_path? && conditions_met?(object, associations)
|
27
29
|
Bullet.debug('detect n + 1 query', "object: #{object.bullet_key}, associations: #{associations}")
|
28
|
-
create_notification
|
30
|
+
create_notification(caller_in_project(object.bullet_key), object.class.to_s, associations)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
@@ -36,16 +38,17 @@ module Bullet
|
|
36
38
|
objects = Array.wrap(object_or_objects)
|
37
39
|
class_names_match_regex = true
|
38
40
|
primary_key_values_are_empty = true
|
39
|
-
|
40
|
-
objects.
|
41
|
+
|
42
|
+
keys_joined = objects.map do |obj|
|
41
43
|
unless obj.class.name =~ /^HABTM_/
|
42
44
|
class_names_match_regex = false
|
43
45
|
end
|
44
46
|
unless obj.bullet_primary_key_value.nil?
|
45
47
|
primary_key_values_are_empty = false
|
46
48
|
end
|
47
|
-
|
48
|
-
end
|
49
|
+
obj.bullet_key
|
50
|
+
end.join(", ")
|
51
|
+
|
49
52
|
unless class_names_match_regex || primary_key_values_are_empty
|
50
53
|
Bullet.debug('Detector::NPlusOneQuery#add_possible_objects', "objects: #{keys_joined}")
|
51
54
|
objects.each { |object| possible_objects.add object.bullet_key }
|
data/lib/bullet/ext/object.rb
CHANGED
@@ -1,30 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Bullet
|
4
|
+
module Ext
|
5
|
+
module Object
|
6
|
+
refine ::Object do
|
7
|
+
attr_writer :bullet_key, :bullet_primary_key_value
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
def bullet_key
|
10
|
+
@bullet_key ||= "#{self.class}:#{bullet_primary_key_value}"
|
11
|
+
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
primary_key = self.class.primary_key
|
15
|
-
else
|
16
|
-
primary_key = :id
|
17
|
-
end
|
13
|
+
def bullet_primary_key_value
|
14
|
+
@bullet_primary_key_value ||= begin
|
15
|
+
return if respond_to?(:persisted?) && !persisted?
|
18
16
|
|
19
|
-
|
20
|
-
end
|
17
|
+
primary_key = self.class.try(:primary_keys) || self.class.try(:primary_key) || :id
|
21
18
|
|
22
|
-
|
19
|
+
bullet_join_potential_composite_primary_key(primary_key)
|
20
|
+
end
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
return send(primary_keys) unless primary_keys.is_a?(Enumerable)
|
23
|
+
private
|
26
24
|
|
27
|
-
|
28
|
-
|
25
|
+
def bullet_join_potential_composite_primary_key(primary_keys)
|
26
|
+
return send(primary_keys) unless primary_keys.is_a?(Enumerable)
|
27
|
+
|
28
|
+
primary_keys.map { |primary_key| send primary_key }
|
29
|
+
.join(',')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
data/lib/bullet/ext/string.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Bullet
|
4
|
+
module Ext
|
5
|
+
module String
|
6
|
+
refine ::String do
|
7
|
+
def bullet_class_name
|
8
|
+
last_colon = self.rindex(':')
|
9
|
+
last_colon ? self[0...last_colon].dup : self.dup
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
6
13
|
end
|
7
14
|
end
|
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
require "bundler"
|
4
4
|
|
5
|
+
using Bullet::Ext::Object
|
6
|
+
|
5
7
|
module Bullet
|
6
8
|
module StackTraceFilter
|
7
9
|
VENDOR_PATH = '/vendor'
|
8
|
-
IS_RUBY_19 = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
|
9
10
|
|
10
11
|
# @param bullet_key[String] - use this to get stored call stack from call_stacks object.
|
11
12
|
def caller_in_project(bullet_key = nil)
|
@@ -54,13 +55,12 @@ module Bullet
|
|
54
55
|
def location_as_path(location)
|
55
56
|
return location if location.is_a?(String)
|
56
57
|
|
57
|
-
|
58
|
+
location.absolute_path.to_s
|
58
59
|
end
|
59
60
|
|
60
61
|
def select_caller_locations(bullet_key = nil)
|
61
|
-
return caller.select { |caller_path| yield caller_path } if IS_RUBY_19
|
62
|
-
|
63
62
|
call_stack = bullet_key ? call_stacks[bullet_key] : caller_locations
|
63
|
+
|
64
64
|
call_stack.select { |location| yield location }
|
65
65
|
end
|
66
66
|
end
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
3
4
|
require 'active_support/core_ext/module/delegation'
|
4
5
|
require 'set'
|
5
6
|
require 'uniform_notifier'
|
@@ -148,42 +149,47 @@ module Bullet
|
|
148
149
|
end
|
149
150
|
|
150
151
|
def start_request
|
151
|
-
Thread.current
|
152
|
-
Thread.current
|
153
|
-
|
154
|
-
Thread.current
|
155
|
-
Thread.current
|
156
|
-
Thread.current
|
157
|
-
Thread.current
|
158
|
-
Thread.current
|
159
|
-
Thread.current
|
160
|
-
Thread.current
|
152
|
+
Thread.current.thread_variable_set(:bullet_start, true)
|
153
|
+
Thread.current.thread_variable_set(:bullet_notification_collector, Bullet::NotificationCollector.new)
|
154
|
+
|
155
|
+
Thread.current.thread_variable_set(:bullet_object_associations, Bullet::Registry::Base.new)
|
156
|
+
Thread.current.thread_variable_set(:bullet_call_object_associations, Bullet::Registry::Base.new)
|
157
|
+
Thread.current.thread_variable_set(:bullet_possible_objects, Bullet::Registry::Object.new)
|
158
|
+
Thread.current.thread_variable_set(:bullet_impossible_objects, Bullet::Registry::Object.new)
|
159
|
+
Thread.current.thread_variable_set(:bullet_inversed_objects, Bullet::Registry::Base.new)
|
160
|
+
Thread.current.thread_variable_set(:bullet_eager_loadings, Bullet::Registry::Association.new)
|
161
|
+
Thread.current.thread_variable_set(:bullet_call_stacks, Bullet::Registry::CallStack.new)
|
162
|
+
|
163
|
+
unless Thread.current.thread_variable_get(:bullet_counter_possible_objects)
|
164
|
+
Thread.current.thread_variable_set(:bullet_counter_possible_objects, Bullet::Registry::Object.new)
|
165
|
+
end
|
161
166
|
|
162
|
-
Thread.current
|
163
|
-
|
167
|
+
unless Thread.current.thread_variable_get(:bullet_counter_impossible_objects)
|
168
|
+
Thread.current.thread_variable_set(:bullet_counter_impossible_objects, Bullet::Registry::Object.new)
|
169
|
+
end
|
164
170
|
end
|
165
171
|
|
166
172
|
def end_request
|
167
|
-
Thread.current
|
168
|
-
Thread.current
|
173
|
+
Thread.current.thread_variable_set(:bullet_start, nil)
|
174
|
+
Thread.current.thread_variable_set(:bullet_notification_collector, nil)
|
169
175
|
|
170
|
-
Thread.current
|
171
|
-
Thread.current
|
172
|
-
Thread.current
|
173
|
-
Thread.current
|
174
|
-
Thread.current
|
175
|
-
Thread.current
|
176
|
+
Thread.current.thread_variable_set(:bullet_object_associations, nil)
|
177
|
+
Thread.current.thread_variable_set(:bullet_call_object_associations, nil)
|
178
|
+
Thread.current.thread_variable_set(:bullet_possible_objects, nil)
|
179
|
+
Thread.current.thread_variable_set(:bullet_impossible_objects, nil)
|
180
|
+
Thread.current.thread_variable_set(:bullet_inversed_objects, nil)
|
181
|
+
Thread.current.thread_variable_set(:bullet_eager_loadings, nil)
|
176
182
|
|
177
|
-
Thread.current
|
178
|
-
Thread.current
|
183
|
+
Thread.current.thread_variable_set(:bullet_counter_possible_objects, nil)
|
184
|
+
Thread.current.thread_variable_set(:bullet_counter_impossible_objects, nil)
|
179
185
|
end
|
180
186
|
|
181
187
|
def start?
|
182
|
-
enable? && Thread.current
|
188
|
+
enable? && Thread.current.thread_variable_get(:bullet_start)
|
183
189
|
end
|
184
190
|
|
185
191
|
def notification_collector
|
186
|
-
Thread.current
|
192
|
+
Thread.current.thread_variable_get(:bullet_notification_collector)
|
187
193
|
end
|
188
194
|
|
189
195
|
def notification?
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 8.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Huang
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-02-10 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: activesupport
|
@@ -59,6 +58,8 @@ files:
|
|
59
58
|
- lib/bullet/active_record61.rb
|
60
59
|
- lib/bullet/active_record70.rb
|
61
60
|
- lib/bullet/active_record71.rb
|
61
|
+
- lib/bullet/active_record72.rb
|
62
|
+
- lib/bullet/active_record80.rb
|
62
63
|
- lib/bullet/bullet_xhr.js
|
63
64
|
- lib/bullet/dependency.rb
|
64
65
|
- lib/bullet/detector.rb
|
@@ -96,7 +97,6 @@ licenses:
|
|
96
97
|
metadata:
|
97
98
|
changelog_uri: https://github.com/flyerhzm/bullet/blob/main/CHANGELOG.md
|
98
99
|
source_code_uri: https://github.com/flyerhzm/bullet
|
99
|
-
post_install_message:
|
100
100
|
rdoc_options: []
|
101
101
|
require_paths:
|
102
102
|
- lib
|
@@ -104,15 +104,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
104
|
requirements:
|
105
105
|
- - ">="
|
106
106
|
- !ruby/object:Gem::Version
|
107
|
-
version:
|
107
|
+
version: 2.7.0
|
108
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
109
|
requirements:
|
110
110
|
- - ">="
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: 1.3.6
|
113
113
|
requirements: []
|
114
|
-
rubygems_version: 3.
|
115
|
-
signing_key:
|
114
|
+
rubygems_version: 3.6.2
|
116
115
|
specification_version: 4
|
117
116
|
summary: help to kill N+1 queries and unused eager loading.
|
118
117
|
test_files: []
|