bullet 8.2.0 → 8.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fff8caa10888c5cc1aee062b08ac4c4df6e5911e9b4c592b3e0c89c3faedf089
4
- data.tar.gz: aebe5eb8c7b8624fc2bbe05f42c4c6e8ba5ef8122f519e4e2f984f83d1ac8762
3
+ metadata.gz: d5c5aff8226198c501ed0c0a3e9d71138bd896f9956cf072b0f92fef79b125c7
4
+ data.tar.gz: 90209fe95da7ad96e110cfdabb96a91a9c403ef9e5824df2877aeab20239f020
5
5
  SHA512:
6
- metadata.gz: 6d60f48c25171229b660274b31ae90689f402d0ea1f46fdf2c63467a550765520b46afb70ff683a8beca75da7ddb86629ba5f58e276667a784d37653f3a94688
7
- data.tar.gz: '06973354f3d5158e1ade0f2898577d772b6669d622b176010b6176dbb8b02e5f67c611fbb55668bfee9c93ea873c1183cd28ba30e778a5a6692d0e050a9a3794'
6
+ metadata.gz: 98dbc38b0e5f77f61617e75bab2b92838bbead761421681791711c917f61282e6ae29fe70fabe645ef8685344a879535fb4634451ff1bb35d560b0fd8a9c3a12
7
+ data.tar.gz: 49f2ebf88e0d99386ebd35a82403ece35167e9ac253013244f9ded4fe76de6b14ea070741847b6048b90ca1e15b6765430a56a180d8f6e6961383be035d08b38
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 8.3.1 (10/24/2026)
4
+
5
+ * Avoid redefining the `footer_position` getter
6
+ * Avoid the CGI loading warning on Ruby 4
7
+ * Keep request state separate for sibling fibers on one thread
8
+
9
+ ## 8.3.0 (10/10/2026)
10
+
11
+ * Add support for ActiveRecord 8.2
12
+
3
13
  ## 8.2.0 (08/29/2026)
4
14
 
5
15
  * Add thread-safe `Bullet.pause`, `Bullet.resume`, `Bullet.paused?`, and `Bullet.skip` APIs
@@ -11,7 +21,7 @@
11
21
 
12
22
  ## 8.1.3 (06/02/2026)
13
23
 
14
- * Handle inversed polymorphic belongs_to false positives
24
+ * Handle inversed polymorphic `belongs_to` false positives
15
25
 
16
26
  ## 8.1.2 (05/25/2026)
17
27
 
@@ -0,0 +1,335 @@
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(*args, **kwargs, &block)
20
+ result = super(*args, **kwargs, &block)
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::Batch.prepend(
65
+ Module.new do
66
+ def call
67
+ if Bullet.start?
68
+ @preloaders.each do |preloader|
69
+ preloader.records.each { |record|
70
+ Bullet::Detector::Association.add_object_associations(record, preloader.associations)
71
+ }
72
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
73
+ end
74
+ end
75
+ super
76
+ end
77
+ end
78
+ )
79
+
80
+ ::ActiveRecord::Associations::Preloader::Branch.prepend(
81
+ Module.new do
82
+ def preloaders_for_reflection(reflection, reflection_records)
83
+ if Bullet.start?
84
+ reflection_records.compact!
85
+ if reflection_records.first.class.name !~ /^HABTM_/
86
+ reflection_records.each { |record|
87
+ Bullet::Detector::Association.add_object_associations(record, reflection.name)
88
+ }
89
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
90
+ end
91
+ end
92
+ super
93
+ end
94
+ end
95
+ )
96
+
97
+ ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
98
+ Module.new do
99
+ def source_preloaders
100
+ if Bullet.start? && !defined?(@source_preloaders)
101
+ preloaders = super
102
+ preloaders.each do |preloader|
103
+ reflection_name = preloader.send(:reflection).name
104
+ preloader.send(:owners).each do |owner|
105
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
106
+ end
107
+ end
108
+ else
109
+ super
110
+ end
111
+ end
112
+
113
+ def through_preloaders
114
+ if Bullet.start? && !defined?(@through_preloaders)
115
+ preloaders = super
116
+ preloaders.each do |preloader|
117
+ reflection_name = preloader.send(:reflection).name
118
+ preloader.send(:owners).each do |owner|
119
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
120
+ end
121
+ end
122
+ else
123
+ super
124
+ end
125
+ end
126
+ end
127
+ )
128
+
129
+ ::ActiveRecord::Associations::JoinDependency.prepend(
130
+ Module.new do
131
+ def instantiate(*args, **kwargs, &block)
132
+ @bullet_eager_loadings = {}
133
+ records = super(*args, **kwargs, &block)
134
+
135
+ if Bullet.start?
136
+ @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
137
+ objects = eager_loadings_hash.keys
138
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
139
+ objects,
140
+ eager_loadings_hash[objects.first].to_a
141
+ )
142
+ end
143
+ end
144
+ records
145
+ end
146
+
147
+ def construct(*args, **kwargs, &block)
148
+ ar_parent, parent, row = args
149
+ if Bullet.start?
150
+ unless ar_parent.nil?
151
+ parent.children.each do |node|
152
+ key = aliases.column_alias(node, node.primary_key)
153
+ id = row[key]
154
+ next unless id.nil?
155
+
156
+ associations = [node.reflection.name]
157
+ if node.reflection.through_reflection?
158
+ associations << node.reflection.through_reflection.name
159
+ end
160
+ associations.each do |association|
161
+ Bullet::Detector::Association.add_object_associations(ar_parent, association)
162
+ Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
163
+ @bullet_eager_loadings[ar_parent.class] ||= {}
164
+ @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
165
+ @bullet_eager_loadings[ar_parent.class][ar_parent] << association
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ super(*args, **kwargs, &block)
172
+ end
173
+
174
+ # call join associations
175
+ def construct_model(*args, **kwargs, &block)
176
+ record, node = args
177
+ result = super(*args, **kwargs, &block)
178
+
179
+ if Bullet.start?
180
+ associations = [node.reflection.name]
181
+ if node.reflection.through_reflection?
182
+ associations << node.reflection.through_reflection.name
183
+ end
184
+ associations.each do |association|
185
+ Bullet::Detector::Association.add_object_associations(record, association)
186
+ Bullet::Detector::NPlusOneQuery.call_association(record, association)
187
+ @bullet_eager_loadings[record.class] ||= {}
188
+ @bullet_eager_loadings[record.class][record] ||= Set.new
189
+ @bullet_eager_loadings[record.class][record] << association
190
+ end
191
+ end
192
+
193
+ result
194
+ end
195
+ end
196
+ )
197
+
198
+ ::ActiveRecord::Associations::Association.prepend(
199
+ Module.new do
200
+ def inversed_from(record)
201
+ if Bullet.start?
202
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
203
+ end
204
+ super
205
+ end
206
+
207
+ def inversed_from_queries(record)
208
+ if Bullet.start? && inversable?(record)
209
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
210
+ end
211
+ super
212
+ end
213
+ end
214
+ )
215
+
216
+ ::ActiveRecord::Associations::CollectionAssociation.prepend(
217
+ Module.new do
218
+ def load_target
219
+ records = super
220
+
221
+ if Bullet.start?
222
+ if is_a? ::ActiveRecord::Associations::ThroughAssociation
223
+ association = owner.association(reflection.through_reflection.name)
224
+ if association.loaded?
225
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
226
+ Array.wrap(association.target).each do |through_record|
227
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
228
+ end
229
+
230
+ if reflection.through_reflection != through_reflection
231
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
232
+ end
233
+ end
234
+ end
235
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
236
+ if records.first.class.name !~ /^HABTM_/
237
+ if records.size > 1
238
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
239
+ Bullet::Detector::CounterCache.add_possible_objects(records)
240
+ elsif records.size == 1
241
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
242
+ Bullet::Detector::CounterCache.add_impossible_object(records.first)
243
+ end
244
+ end
245
+ end
246
+ records
247
+ end
248
+
249
+ def empty?
250
+ if Bullet.start? && !reflection.has_cached_counter?
251
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
252
+ end
253
+ super
254
+ end
255
+
256
+ def include?(object)
257
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations) if Bullet.start?
258
+ super
259
+ end
260
+ end
261
+ )
262
+
263
+ ::ActiveRecord::Associations::SingularAssociation.prepend(
264
+ Module.new do
265
+ # call has_one and belongs_to associations
266
+ def reader
267
+ result = super
268
+
269
+ if Bullet.start?
270
+ if owner.class.name !~ /^HABTM_/
271
+ if is_a? ::ActiveRecord::Associations::ThroughAssociation
272
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
273
+ association = owner.association(reflection.through_reflection.name)
274
+ Array.wrap(association.target).each do |through_record|
275
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
276
+ end
277
+
278
+ if reflection.through_reflection != through_reflection
279
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
280
+ end
281
+ end
282
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
283
+
284
+ if Bullet::Detector::NPlusOneQuery.impossible?(owner)
285
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
286
+ else
287
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
288
+ end
289
+ end
290
+ end
291
+ result
292
+ end
293
+ end
294
+ )
295
+
296
+ ::ActiveRecord::Associations::HasManyAssociation.prepend(
297
+ Module.new do
298
+ def empty?
299
+ if Bullet.start? && !reflection.has_cached_counter?
300
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
301
+ end
302
+ super
303
+ end
304
+
305
+ def count_records
306
+ result = reflection.has_cached_counter?
307
+ if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
308
+ Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
309
+ end
310
+ super
311
+ end
312
+ end
313
+ )
314
+
315
+ ::ActiveRecord::Associations::CollectionProxy.prepend(
316
+ Module.new do
317
+ def count(column_name = nil)
318
+ if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
319
+ Bullet::Detector::CounterCache.add_counter_cache(
320
+ proxy_association.owner,
321
+ proxy_association.reflection.name
322
+ )
323
+ Bullet::Detector::NPlusOneQuery.call_association(
324
+ proxy_association.owner,
325
+ proxy_association.reflection.name,
326
+ caller_locations
327
+ )
328
+ end
329
+ super(column_name)
330
+ end
331
+ end
332
+ )
333
+ end
334
+ end
335
+ end
@@ -25,6 +25,8 @@ module Bullet
25
25
  'active_record80'
26
26
  elsif active_record81?
27
27
  'active_record81'
28
+ elsif active_record82?
29
+ 'active_record82'
28
30
  else
29
31
  raise "Bullet does not support active_record #{::ActiveRecord::VERSION::STRING} yet"
30
32
  end
@@ -84,6 +86,10 @@ module Bullet
84
86
  active_record8? && ::ActiveRecord::VERSION::MINOR == 1
85
87
  end
86
88
 
89
+ def active_record82?
90
+ active_record8? && ::ActiveRecord::VERSION::MINOR == 2
91
+ end
92
+
87
93
  def mongoid4x?
88
94
  mongoid? && ::Mongoid::VERSION =~ /\A4/
89
95
  end
@@ -36,7 +36,7 @@ module Bullet
36
36
  # that the objects may cause N+1 query.
37
37
  # e.g. { Post => ["Post:1", "Post:2"] }
38
38
  def possible_objects
39
- Thread.current.thread_variable_get(:bullet_possible_objects)
39
+ Bullet.state[:bullet_possible_objects]
40
40
  end
41
41
 
42
42
  # impossible_objects keep the class to objects relationships
@@ -45,7 +45,7 @@ module Bullet
45
45
  # if find collection returns only one object, then the object is impossible object,
46
46
  # impossible_objects are used to avoid treating 1+1 query to N+1 query.
47
47
  def impossible_objects
48
- Thread.current.thread_variable_get(:bullet_impossible_objects)
48
+ Bullet.state[:bullet_impossible_objects]
49
49
  end
50
50
 
51
51
  private
@@ -56,7 +56,7 @@ module Bullet
56
56
  # the object_associations keep all associations that may be or may no be
57
57
  # unpreload associations or unused preload associations.
58
58
  def object_associations
59
- Thread.current.thread_variable_get(:bullet_object_associations)
59
+ Bullet.state[:bullet_object_associations]
60
60
  end
61
61
 
62
62
  # call_object_associations keep the object relationships
@@ -64,27 +64,27 @@ module Bullet
64
64
  # e.g. { "Post:1" => [:comments] }
65
65
  # they are used to detect unused preload associations.
66
66
  def call_object_associations
67
- Thread.current.thread_variable_get(:bullet_call_object_associations)
67
+ Bullet.state[:bullet_call_object_associations]
68
68
  end
69
69
 
70
70
  # inversed_objects keeps object relationships
71
71
  # that association is inversed.
72
72
  # e.g. { "Comment:1" => ["post"] }
73
73
  def inversed_objects
74
- Thread.current.thread_variable_get(:bullet_inversed_objects)
74
+ Bullet.state[:bullet_inversed_objects]
75
75
  end
76
76
 
77
77
  # eager_loadings keep the object relationships
78
78
  # that the associations are preloaded by find :include.
79
79
  # e.g. { ["Post:1", "Post:2"] => [:comments, :user] }
80
80
  def eager_loadings
81
- Thread.current.thread_variable_get(:bullet_eager_loadings)
81
+ Bullet.state[:bullet_eager_loadings]
82
82
  end
83
83
 
84
84
  # call_stacks keeps stacktraces where querie-objects were called from.
85
85
  # e.g. { 'Object:111' => [SomeProject/app/controllers/...] }
86
86
  def call_stacks
87
- Thread.current.thread_variable_get(:bullet_call_stacks)
87
+ Bullet.state[:bullet_call_stacks]
88
88
  end
89
89
  end
90
90
  end
@@ -46,11 +46,11 @@ module Bullet
46
46
  end
47
47
 
48
48
  def possible_objects
49
- Thread.current.thread_variable_get(:bullet_counter_possible_objects)
49
+ Bullet.state[:bullet_counter_possible_objects]
50
50
  end
51
51
 
52
52
  def impossible_objects
53
- Thread.current.thread_variable_get(:bullet_counter_impossible_objects)
53
+ Bullet.state[:bullet_counter_impossible_objects]
54
54
  end
55
55
 
56
56
  private
data/lib/bullet/rack.rb CHANGED
@@ -2,7 +2,12 @@
2
2
 
3
3
  require 'rack/request'
4
4
  require 'json'
5
- require 'cgi'
5
+
6
+ if RUBY_VERSION.to_i >= 4
7
+ require 'cgi/escape'
8
+ else
9
+ require 'cgi'
10
+ end
6
11
 
7
12
  module Bullet
8
13
  class Rack
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bullet
4
- VERSION = '8.2.0'
4
+ VERSION = '8.3.1'
5
5
  end
data/lib/bullet.rb CHANGED
@@ -39,10 +39,10 @@ module Bullet
39
39
  :counter_cache_enable,
40
40
  :stacktrace_includes,
41
41
  :stacktrace_excludes,
42
- :skip_html_injection
42
+ :skip_html_injection,
43
+ :footer_position
43
44
  attr_reader :safelist
44
45
  attr_accessor :add_footer,
45
- :footer_position,
46
46
  :orm_patches_applied,
47
47
  :skip_http_headers,
48
48
  :always_append_html_body,
@@ -149,56 +149,71 @@ module Bullet
149
149
  puts "[Bullet][#{title}] #{message}" if ENV['BULLET_DEBUG'] == 'true'
150
150
  end
151
151
 
152
+ # Fiber storage reaches child fibers; start_request gives each request its own, and the owner check keeps it off new threads.
153
+ def state
154
+ unless Fiber.respond_to?(:[])
155
+ return Thread.current.thread_variable_get(:bullet_state) || Thread.current.thread_variable_set(:bullet_state, {})
156
+ end
157
+
158
+ current = Fiber[:bullet_state]
159
+ return current if current && current[:owner].equal?(Thread.current)
160
+
161
+ Fiber[:bullet_state] = { owner: Thread.current }
162
+ end
163
+
152
164
  def start_request
153
- Thread.current.thread_variable_set(:bullet_start, true)
154
- Thread.current.thread_variable_set(:bullet_notification_collector, Bullet::NotificationCollector.new)
155
-
156
- Thread.current.thread_variable_set(:bullet_object_associations, Bullet::Registry::Base.new)
157
- Thread.current.thread_variable_set(:bullet_call_object_associations, Bullet::Registry::Base.new)
158
- Thread.current.thread_variable_set(:bullet_possible_objects, Bullet::Registry::Object.new)
159
- Thread.current.thread_variable_set(:bullet_impossible_objects, Bullet::Registry::Object.new)
160
- Thread.current.thread_variable_set(:bullet_inversed_objects, Bullet::Registry::Base.new)
161
- Thread.current.thread_variable_set(:bullet_eager_loadings, Bullet::Registry::Association.new)
162
- Thread.current.thread_variable_set(:bullet_call_stacks, Bullet::Registry::CallStack.new)
163
-
164
- unless Thread.current.thread_variable_get(:bullet_counter_possible_objects)
165
- Thread.current.thread_variable_set(:bullet_counter_possible_objects, Bullet::Registry::Object.new)
165
+ if Fiber.respond_to?(:[])
166
+ Fiber[:bullet_state] = state.slice(:owner)
167
+ end
168
+ Bullet.state[:bullet_start] = true
169
+ Bullet.state[:bullet_notification_collector] = Bullet::NotificationCollector.new
170
+
171
+ Bullet.state[:bullet_object_associations] = Bullet::Registry::Base.new
172
+ Bullet.state[:bullet_call_object_associations] = Bullet::Registry::Base.new
173
+ Bullet.state[:bullet_possible_objects] = Bullet::Registry::Object.new
174
+ Bullet.state[:bullet_impossible_objects] = Bullet::Registry::Object.new
175
+ Bullet.state[:bullet_inversed_objects] = Bullet::Registry::Base.new
176
+ Bullet.state[:bullet_eager_loadings] = Bullet::Registry::Association.new
177
+ Bullet.state[:bullet_call_stacks] = Bullet::Registry::CallStack.new
178
+
179
+ unless Bullet.state[:bullet_counter_possible_objects]
180
+ Bullet.state[:bullet_counter_possible_objects] = Bullet::Registry::Object.new
166
181
  end
167
182
 
168
- unless Thread.current.thread_variable_get(:bullet_counter_impossible_objects)
169
- Thread.current.thread_variable_set(:bullet_counter_impossible_objects, Bullet::Registry::Object.new)
183
+ unless Bullet.state[:bullet_counter_impossible_objects]
184
+ Bullet.state[:bullet_counter_impossible_objects] = Bullet::Registry::Object.new
170
185
  end
171
186
  end
172
187
 
173
188
  def end_request
174
- Thread.current.thread_variable_set(:bullet_start, nil)
175
- Thread.current.thread_variable_set(:bullet_notification_collector, nil)
189
+ Bullet.state[:bullet_start] = nil
190
+ Bullet.state[:bullet_notification_collector] = nil
176
191
 
177
- Thread.current.thread_variable_set(:bullet_object_associations, nil)
178
- Thread.current.thread_variable_set(:bullet_call_object_associations, nil)
179
- Thread.current.thread_variable_set(:bullet_possible_objects, nil)
180
- Thread.current.thread_variable_set(:bullet_impossible_objects, nil)
181
- Thread.current.thread_variable_set(:bullet_inversed_objects, nil)
182
- Thread.current.thread_variable_set(:bullet_eager_loadings, nil)
192
+ Bullet.state[:bullet_object_associations] = nil
193
+ Bullet.state[:bullet_call_object_associations] = nil
194
+ Bullet.state[:bullet_possible_objects] = nil
195
+ Bullet.state[:bullet_impossible_objects] = nil
196
+ Bullet.state[:bullet_inversed_objects] = nil
197
+ Bullet.state[:bullet_eager_loadings] = nil
183
198
 
184
- Thread.current.thread_variable_set(:bullet_counter_possible_objects, nil)
185
- Thread.current.thread_variable_set(:bullet_counter_impossible_objects, nil)
199
+ Bullet.state[:bullet_counter_possible_objects] = nil
200
+ Bullet.state[:bullet_counter_impossible_objects] = nil
186
201
  end
187
202
 
188
203
  def start?
189
- enable? && Thread.current.thread_variable_get(:bullet_start)
204
+ enable? && Bullet.state[:bullet_start]
190
205
  end
191
206
 
192
207
  def pause
193
- Thread.current.thread_variable_set(:bullet_start, false)
208
+ Bullet.state[:bullet_start] = false
194
209
  end
195
210
 
196
211
  def resume
197
- Thread.current.thread_variable_set(:bullet_start, true)
212
+ Bullet.state[:bullet_start] = true
198
213
  end
199
214
 
200
215
  def paused?
201
- enable? && !Thread.current.thread_variable_get(:bullet_start)
216
+ enable? && !Bullet.state[:bullet_start]
202
217
  end
203
218
 
204
219
  def skip
@@ -210,7 +225,7 @@ module Bullet
210
225
  end
211
226
 
212
227
  def notification_collector
213
- Thread.current.thread_variable_get(:bullet_notification_collector)
228
+ Bullet.state[:bullet_notification_collector]
214
229
  end
215
230
 
216
231
  def notification?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.2.0
4
+ version: 8.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
@@ -82,6 +82,7 @@ files:
82
82
  - lib/bullet/active_record72.rb
83
83
  - lib/bullet/active_record80.rb
84
84
  - lib/bullet/active_record81.rb
85
+ - lib/bullet/active_record82.rb
85
86
  - lib/bullet/bullet_xhr.js
86
87
  - lib/bullet/dependency.rb
87
88
  - lib/bullet/detector.rb
@@ -134,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
135
  - !ruby/object:Gem::Version
135
136
  version: 1.3.6
136
137
  requirements: []
137
- rubygems_version: 4.0.6
138
+ rubygems_version: 4.0.20
138
139
  specification_version: 4
139
140
  summary: help to kill N+1 queries and unused eager loading.
140
141
  test_files: []