bullet 7.2.0 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a0528fba283865b1a94ba6a82d3f5941c63a62e7b34a08332d6208dfde7f28ba
4
- data.tar.gz: 21ad1b7a9c1ab8473ddfff4fcd260346b5088a2f8cf615fbe74abfbe2e70c307
3
+ metadata.gz: '0309ea5abf7ab699c893c093abed5605b8afbb93ca1034cac1af01d8afcbd0da'
4
+ data.tar.gz: fe9a9a6b61d3c2d9235fb9bfe9f7ba4f141fca5dccf10707ffee86dfcd84b9c3
5
5
  SHA512:
6
- metadata.gz: 8f6a75db29ab14c89ebd57664f7d96ee5f006fbc816dcbc442678ded0171712aadd360dbb204a567519cab8a49879c067b83a090ea3a8999d212b6801d60fa92
7
- data.tar.gz: 4b51f257fb70205d068e7f233b0e5e30967da936e19481bd9d956b0303f85b67b95792a00a92f272e04333d3861dd69d6ac916c156d06b5db9f5136e0b543dd9
6
+ metadata.gz: dbc0c561b35efc8a3e131aae16f75382c319f2a6cffeeb48bee8cfa738d88eacd2b53026c59cdcf923e691bc785f9413fa0754cccb2419f2589c36193a25b7da
7
+ data.tar.gz: f9a723c0531c67c673612da26db9d1a3a365f9d912fd8d9dbdf2e4bcd24ec89f18f3662c743e5a201d89c6e886aacea92880b0f3460613b9a8f10be0dff2ef7b
data/CHANGELOG.md CHANGED
@@ -1,8 +1,16 @@
1
1
  ## Next Release
2
2
 
3
+ ## 8.0.0 (11/10/2024)
4
+
5
+ * Support Rails 8
6
+ * Drop Rails 4.0 and 4.1 support
7
+ * Require Ruby at least 2.7.0
8
+ * Store global objects into thread-local variables
9
+ * Avoid globally polluting `::String` and `::Object` classes
10
+
3
11
  ## 7.2.0 (07/12/2024)
4
12
 
5
- * Support rails 7.2
13
+ * Support Rails 7.2
6
14
  * Fix count method signature for active_record5 and active_record60
7
15
 
8
16
  ## 7.1.6 (01/16/2024)
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 - 2022 Richard Huang (flyerhzm@gmail.com)
1
+ Copyright (c) 2009 - 2024 Richard Huang (flyerhzm@gmail.com)
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  ![Main workflow](https://github.com/flyerhzm/bullet/actions/workflows/main.yml/badge.svg)
4
4
  [![Gem Version](https://badge.fury.io/rb/bullet.svg)](http://badge.fury.io/rb/bullet)
5
5
  [![AwesomeCode Status for flyerhzm/bullet](https://awesomecode.io/projects/6755235b-e2c1-459e-bf92-b8b13d0c0472/status)](https://awesomecode.io/repos/flyerhzm/bullet)
6
- [![Coderwall Endorse](http://api.coderwall.com/flyerhzm/endorsecount.png)](http://coderwall.com/flyerhzm)
6
+ [![Coderwall Endorse](https://coderwall.com/flyerhzm/endorsecount.png)](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
- * [http://weblog.rubyonrails.org/2009/10/22/community-highlights](http://weblog.rubyonrails.org/2009/10/22/community-highlights)
23
+ * [https://rubyonrails.org/2009/10/22/community-highlights](https://rubyonrails.org/2009/10/22/community-highlights)
24
24
 
25
25
  ## Install
26
26
 
@@ -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
@@ -35,6 +35,8 @@ module Bullet
35
35
  'active_record71'
36
36
  elsif active_record72?
37
37
  'active_record72'
38
+ elsif active_record80?
39
+ 'active_record80'
38
40
  else
39
41
  raise "Bullet does not support active_record #{::ActiveRecord::VERSION::STRING} yet"
40
42
  end
@@ -76,6 +78,10 @@ module Bullet
76
78
  active_record? && ::ActiveRecord::VERSION::MAJOR == 7
77
79
  end
78
80
 
81
+ def active_record8?
82
+ active_record? && ::ActiveRecord::VERSION::MAJOR == 8
83
+ end
84
+
79
85
  def active_record40?
80
86
  active_record4? && ::ActiveRecord::VERSION::MINOR == 0
81
87
  end
@@ -120,6 +126,10 @@ module Bullet
120
126
  active_record7? && ::ActiveRecord::VERSION::MINOR == 2
121
127
  end
122
128
 
129
+ def active_record80?
130
+ active_record8? && ::ActiveRecord::VERSION::MINOR == 0
131
+ end
132
+
123
133
  def mongoid4x?
124
134
  mongoid? && ::Mongoid::VERSION =~ /\A4/
125
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[:bullet_possible_objects]
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[:bullet_impossible_objects]
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[:bullet_object_associations]
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[:bullet_call_object_associations]
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[:bullet_inversed_objects]
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[:bullet_eager_loadings]
81
+ Thread.current.thread_variable_get(:bullet_eager_loadings)
80
82
  end
81
83
 
82
84
  # cal_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[:bullet_call_stacks]
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[:bullet_counter_possible_objects]
49
+ Thread.current.thread_variable_get(:bullet_counter_possible_objects)
48
50
  end
49
51
 
50
52
  def impossible_objects
51
- Thread.current[:bullet_counter_impossible_objects]
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
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ using Bullet::Ext::Object
4
+ using Bullet::Ext::String
5
+
3
6
  module Bullet
4
7
  module Detector
5
8
  class UnusedEagerLoading < Association
@@ -1,30 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Object
4
- def bullet_key
5
- "#{self.class}:#{bullet_primary_key_value}"
6
- end
3
+ module Bullet
4
+ module Ext
5
+ module Object
6
+ refine ::Object do
7
+ def bullet_key
8
+ "#{self.class}:#{bullet_primary_key_value}"
9
+ end
7
10
 
8
- def bullet_primary_key_value
9
- return if respond_to?(:persisted?) && !persisted?
11
+ def bullet_primary_key_value
12
+ return if respond_to?(:persisted?) && !persisted?
10
13
 
11
- if self.class.respond_to?(:primary_keys) && self.class.primary_keys
12
- primary_key = self.class.primary_keys
13
- elsif self.class.respond_to?(:primary_key) && self.class.primary_key
14
- primary_key = self.class.primary_key
15
- else
16
- primary_key = :id
17
- end
14
+ if self.class.respond_to?(:primary_keys) && self.class.primary_keys
15
+ primary_key = self.class.primary_keys
16
+ elsif self.class.respond_to?(:primary_key) && self.class.primary_key
17
+ primary_key = self.class.primary_key
18
+ else
19
+ primary_key = :id
20
+ end
18
21
 
19
- bullet_join_potential_composite_primary_key(primary_key)
20
- end
22
+ bullet_join_potential_composite_primary_key(primary_key)
23
+ end
21
24
 
22
- private
25
+ private
23
26
 
24
- def bullet_join_potential_composite_primary_key(primary_keys)
25
- return send(primary_keys) unless primary_keys.is_a?(Enumerable)
27
+ def bullet_join_potential_composite_primary_key(primary_keys)
28
+ return send(primary_keys) unless primary_keys.is_a?(Enumerable)
26
29
 
27
- primary_keys.map { |primary_key| send primary_key }
28
- .join(',')
30
+ primary_keys.map { |primary_key| send primary_key }
31
+ .join(',')
32
+ end
33
+ end
34
+ end
29
35
  end
30
36
  end
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class String
4
- def bullet_class_name
5
- sub(/:[^:]*?$/, '')
3
+ module Bullet
4
+ module Ext
5
+ module String
6
+ refine ::String do
7
+ def bullet_class_name
8
+ sub(/:[^:]*?$/, '')
9
+ end
10
+ end
11
+ end
6
12
  end
7
13
  end
@@ -5,7 +5,7 @@ module Bullet
5
5
  class CallStack < Base
6
6
  # remembers found association backtrace
7
7
  def add(key)
8
- @registry[key] = Thread.current.backtrace
8
+ @registry[key] ||= Thread.current.backtrace
9
9
  end
10
10
  end
11
11
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ using Bullet::Ext::Object
4
+ using Bullet::Ext::String
5
+
3
6
  module Bullet
4
7
  module Registry
5
8
  class Object < Base
@@ -2,6 +2,8 @@
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'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bullet
4
- VERSION = '7.2.0'
4
+ VERSION = '8.0.0'
5
5
  end
data/lib/bullet.rb CHANGED
@@ -148,42 +148,47 @@ module Bullet
148
148
  end
149
149
 
150
150
  def start_request
151
- Thread.current[:bullet_start] = true
152
- Thread.current[:bullet_notification_collector] = Bullet::NotificationCollector.new
153
-
154
- Thread.current[:bullet_object_associations] = Bullet::Registry::Base.new
155
- Thread.current[:bullet_call_object_associations] = Bullet::Registry::Base.new
156
- Thread.current[:bullet_possible_objects] = Bullet::Registry::Object.new
157
- Thread.current[:bullet_impossible_objects] = Bullet::Registry::Object.new
158
- Thread.current[:bullet_inversed_objects] = Bullet::Registry::Base.new
159
- Thread.current[:bullet_eager_loadings] = Bullet::Registry::Association.new
160
- Thread.current[:bullet_call_stacks] = Bullet::Registry::CallStack.new
151
+ Thread.current.thread_variable_set(:bullet_start, true)
152
+ Thread.current.thread_variable_set(:bullet_notification_collector, Bullet::NotificationCollector.new)
153
+
154
+ Thread.current.thread_variable_set(:bullet_object_associations, Bullet::Registry::Base.new)
155
+ Thread.current.thread_variable_set(:bullet_call_object_associations, Bullet::Registry::Base.new)
156
+ Thread.current.thread_variable_set(:bullet_possible_objects, Bullet::Registry::Object.new)
157
+ Thread.current.thread_variable_set(:bullet_impossible_objects, Bullet::Registry::Object.new)
158
+ Thread.current.thread_variable_set(:bullet_inversed_objects, Bullet::Registry::Base.new)
159
+ Thread.current.thread_variable_set(:bullet_eager_loadings, Bullet::Registry::Association.new)
160
+ Thread.current.thread_variable_set(:bullet_call_stacks, Bullet::Registry::CallStack.new)
161
+
162
+ unless Thread.current.thread_variable_get(:bullet_counter_possible_objects)
163
+ Thread.current.thread_variable_set(:bullet_counter_possible_objects, Bullet::Registry::Object.new)
164
+ end
161
165
 
162
- Thread.current[:bullet_counter_possible_objects] ||= Bullet::Registry::Object.new
163
- Thread.current[:bullet_counter_impossible_objects] ||= Bullet::Registry::Object.new
166
+ unless Thread.current.thread_variable_get(:bullet_counter_impossible_objects)
167
+ Thread.current.thread_variable_set(:bullet_counter_impossible_objects, Bullet::Registry::Object.new)
168
+ end
164
169
  end
165
170
 
166
171
  def end_request
167
- Thread.current[:bullet_start] = nil
168
- Thread.current[:bullet_notification_collector] = nil
172
+ Thread.current.thread_variable_set(:bullet_start, nil)
173
+ Thread.current.thread_variable_set(:bullet_notification_collector, nil)
169
174
 
170
- Thread.current[:bullet_object_associations] = nil
171
- Thread.current[:bullet_call_object_associations] = nil
172
- Thread.current[:bullet_possible_objects] = nil
173
- Thread.current[:bullet_impossible_objects] = nil
174
- Thread.current[:bullet_inversed_objects] = nil
175
- Thread.current[:bullet_eager_loadings] = nil
175
+ Thread.current.thread_variable_set(:bullet_object_associations, nil)
176
+ Thread.current.thread_variable_set(:bullet_call_object_associations, nil)
177
+ Thread.current.thread_variable_set(:bullet_possible_objects, nil)
178
+ Thread.current.thread_variable_set(:bullet_impossible_objects, nil)
179
+ Thread.current.thread_variable_set(:bullet_inversed_objects, nil)
180
+ Thread.current.thread_variable_set(:bullet_eager_loadings, nil)
176
181
 
177
- Thread.current[:bullet_counter_possible_objects] = nil
178
- Thread.current[:bullet_counter_impossible_objects] = nil
182
+ Thread.current.thread_variable_set(:bullet_counter_possible_objects, nil)
183
+ Thread.current.thread_variable_set(:bullet_counter_impossible_objects, nil)
179
184
  end
180
185
 
181
186
  def start?
182
- enable? && Thread.current[:bullet_start]
187
+ enable? && Thread.current.thread_variable_get(:bullet_start)
183
188
  end
184
189
 
185
190
  def notification_collector
186
- Thread.current[:bullet_notification_collector]
191
+ Thread.current.thread_variable_get(:bullet_notification_collector)
187
192
  end
188
193
 
189
194
  def notification?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.0
4
+ version: 8.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-12 00:00:00.000000000 Z
11
+ date: 2024-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -60,6 +60,7 @@ files:
60
60
  - lib/bullet/active_record70.rb
61
61
  - lib/bullet/active_record71.rb
62
62
  - lib/bullet/active_record72.rb
63
+ - lib/bullet/active_record80.rb
63
64
  - lib/bullet/bullet_xhr.js
64
65
  - lib/bullet/dependency.rb
65
66
  - lib/bullet/detector.rb
@@ -105,14 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
105
106
  requirements:
106
107
  - - ">="
107
108
  - !ruby/object:Gem::Version
108
- version: '2.3'
109
+ version: 2.7.0
109
110
  required_rubygems_version: !ruby/object:Gem::Requirement
110
111
  requirements:
111
112
  - - ">="
112
113
  - !ruby/object:Gem::Version
113
114
  version: 1.3.6
114
115
  requirements: []
115
- rubygems_version: 3.5.14
116
+ rubygems_version: 3.5.16
116
117
  signing_key:
117
118
  specification_version: 4
118
119
  summary: help to kill N+1 queries and unused eager loading.