bullet 8.1.0.beta1 → 8.1.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: 2574a64c0e7be33a0d8ba57e0c23555e70b09999ae9d6d2d8ce0abf30222c782
4
- data.tar.gz: 1da3e33d8752367ff389f41f16eff4e7f314084954160a21cc5aac8f1f3b0fca
3
+ metadata.gz: 4f10d7c7ed8bf9cb6e6b3f0d8d2757bfa71a66d8c4f90da0ce708cfce06eddb8
4
+ data.tar.gz: 4986e5b6390339bd6034a598a5f24678dd98c1db907f07de3a2aac1cef4501fd
5
5
  SHA512:
6
- metadata.gz: 4b324a99664cfbc4892cee40c2c80f32a46b313c0ea155de6eb36c4809d372e90c8ed5c3eaf20d90de39fbfe03ce1251d128c56f6a30343a2fa25b9d152cff6d
7
- data.tar.gz: 8be2ed0c9d8ce3e9868c554919f9d5e08b04f16876b1f7999470c05a47ffae82f5c896fd38f39518aef3f8f952b44ffe072f3363bd7e7a24b33bdb53cf51e809
6
+ metadata.gz: 323f11d8aee1ba3175eb02795aafb800ad1262f4da84333698fa2f73011b5f9912ad7c38fe37f347ac1b492e90cff87db322433fc6ef55262ab1ecf2e6cc02d7
7
+ data.tar.gz: e44277b7412ff505bb3c21047f8eeff5774f367375989192ef27367102eae91f04eb6625f89110160181690ab440051ae6dc2db39d0b5eb89b30fe47a164eab9
data/CHANGELOG.md CHANGED
@@ -1,9 +1,14 @@
1
- ## Next Release
1
+ ## 8.1.1 (04/23/2026)
2
2
 
3
- ## 8.1.0.beta1 (10/16/2025)
3
+ * Fix ActiveRecord 8.1 patch-level method signature compatibility; test against Rails 8.1.3.
4
+ * Handle string associations in safelist for Action Text
5
+ * Enhance N+1 query detection by including caller stack in association calls
6
+ * Update external links in README.md
7
+
8
+ ## 8.1.0 (10/23/2025)
4
9
 
5
10
  * Make `get_relation` private
6
- * Add support for ActiveRecord 8.1.0.beta1
11
+ * Support Rails 8.1
7
12
 
8
13
  ## 8.0.8 (05/30/2025)
9
14
 
data/README.md CHANGED
@@ -17,10 +17,9 @@ If you use activerecord 3.x, please use bullet < 5.5.0
17
17
 
18
18
  ## External Introduction
19
19
 
20
- * [http://railscasts.com/episodes/372-bullet](http://railscasts.com/episodes/372-bullet)
21
- * [http://ruby5.envylabs.com/episodes/9-episode-8-september-8-2009](http://ruby5.envylabs.com/episodes/9-episode-8-september-8-2009)
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
20
  * [https://rubyonrails.org/2009/10/22/community-highlights](https://rubyonrails.org/2009/10/22/community-highlights)
21
+ * [https://www.shakacode.com/blog/eliminate-N-1-queries-with-bullet/](https://www.shakacode.com/blog/eliminate-N-1-queries-with-bullet/)
22
+ * [https://reinteractive.com/articles/ruby-on-rails-community/elevating-your-code-quality-bullet-gem-and-query-prevention-in-testing](https://reinteractive.com/articles/ruby-on-rails-community/elevating-your-code-quality-bullet-gem-and-query-prevention-in-testing)
24
23
 
25
24
  ## Install
26
25
 
@@ -255,11 +255,10 @@ module Bullet
255
255
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
256
256
  Module.new do
257
257
  def empty?
258
- result = super
259
258
  if Bullet.start? && !reflection.has_cached_counter?
260
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
259
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
261
260
  end
262
- result
261
+ super
263
262
  end
264
263
 
265
264
  def count_records
@@ -237,11 +237,10 @@ module Bullet
237
237
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
238
238
  Module.new do
239
239
  def empty?
240
- result = super
241
240
  if Bullet.start? && !reflection.has_cached_counter?
242
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
241
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
243
242
  end
244
- result
243
+ super
245
244
  end
246
245
 
247
246
  def count_records
@@ -216,13 +216,13 @@ module Bullet
216
216
 
217
217
  def empty?
218
218
  if Bullet.start? && !reflection.has_cached_counter?
219
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
219
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
220
220
  end
221
221
  super
222
222
  end
223
223
 
224
224
  def include?(object)
225
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
225
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations) if Bullet.start?
226
226
  super
227
227
  end
228
228
  end
@@ -264,11 +264,10 @@ module Bullet
264
264
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
265
265
  Module.new do
266
266
  def empty?
267
- result = super
268
267
  if Bullet.start? && !reflection.has_cached_counter?
269
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
268
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
270
269
  end
271
- result
270
+ super
272
271
  end
273
272
 
274
273
  def count_records
@@ -291,7 +290,8 @@ module Bullet
291
290
  )
292
291
  Bullet::Detector::NPlusOneQuery.call_association(
293
292
  proxy_association.owner,
294
- proxy_association.reflection.name
293
+ proxy_association.reflection.name,
294
+ caller_locations
295
295
  )
296
296
  end
297
297
  super(column_name)
@@ -216,13 +216,13 @@ module Bullet
216
216
 
217
217
  def empty?
218
218
  if Bullet.start? && !reflection.has_cached_counter?
219
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
219
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
220
220
  end
221
221
  super
222
222
  end
223
223
 
224
224
  def include?(object)
225
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
225
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations) if Bullet.start?
226
226
  super
227
227
  end
228
228
  end
@@ -264,11 +264,10 @@ module Bullet
264
264
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
265
265
  Module.new do
266
266
  def empty?
267
- result = super
268
267
  if Bullet.start? && !reflection.has_cached_counter?
269
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
268
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
270
269
  end
271
- result
270
+ super
272
271
  end
273
272
 
274
273
  def count_records
@@ -291,7 +290,8 @@ module Bullet
291
290
  )
292
291
  Bullet::Detector::NPlusOneQuery.call_association(
293
292
  proxy_association.owner,
294
- proxy_association.reflection.name
293
+ proxy_association.reflection.name,
294
+ caller_locations
295
295
  )
296
296
  end
297
297
  super(column_name)
@@ -232,13 +232,13 @@ module Bullet
232
232
 
233
233
  def empty?
234
234
  if Bullet.start? && !reflection.has_cached_counter?
235
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
235
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
236
236
  end
237
237
  super
238
238
  end
239
239
 
240
240
  def include?(object)
241
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
241
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations) if Bullet.start?
242
242
  super
243
243
  end
244
244
  end
@@ -280,11 +280,10 @@ module Bullet
280
280
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
281
281
  Module.new do
282
282
  def empty?
283
- result = super
284
283
  if Bullet.start? && !reflection.has_cached_counter?
285
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
284
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
286
285
  end
287
- result
286
+ super
288
287
  end
289
288
 
290
289
  def count_records
@@ -307,7 +306,8 @@ module Bullet
307
306
  )
308
307
  Bullet::Detector::NPlusOneQuery.call_association(
309
308
  proxy_association.owner,
310
- proxy_association.reflection.name
309
+ proxy_association.reflection.name,
310
+ caller_locations
311
311
  )
312
312
  end
313
313
  super(column_name)
@@ -232,13 +232,13 @@ module Bullet
232
232
 
233
233
  def empty?
234
234
  if Bullet.start? && !reflection.has_cached_counter?
235
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
235
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
236
236
  end
237
237
  super
238
238
  end
239
239
 
240
240
  def include?(object)
241
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
241
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations) if Bullet.start?
242
242
  super
243
243
  end
244
244
  end
@@ -280,11 +280,10 @@ module Bullet
280
280
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
281
281
  Module.new do
282
282
  def empty?
283
- result = super
284
283
  if Bullet.start? && !reflection.has_cached_counter?
285
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
284
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
286
285
  end
287
- result
286
+ super
288
287
  end
289
288
 
290
289
  def count_records
@@ -307,7 +306,8 @@ module Bullet
307
306
  )
308
307
  Bullet::Detector::NPlusOneQuery.call_association(
309
308
  proxy_association.owner,
310
- proxy_association.reflection.name
309
+ proxy_association.reflection.name,
310
+ caller_locations
311
311
  )
312
312
  end
313
313
  super(column_name)
@@ -232,13 +232,13 @@ module Bullet
232
232
 
233
233
  def empty?
234
234
  if Bullet.start? && !reflection.has_cached_counter?
235
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
235
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
236
236
  end
237
237
  super
238
238
  end
239
239
 
240
240
  def include?(object)
241
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
241
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations) if Bullet.start?
242
242
  super
243
243
  end
244
244
  end
@@ -280,11 +280,10 @@ module Bullet
280
280
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
281
281
  Module.new do
282
282
  def empty?
283
- result = super
284
283
  if Bullet.start? && !reflection.has_cached_counter?
285
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
284
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
286
285
  end
287
- result
286
+ super
288
287
  end
289
288
 
290
289
  def count_records
@@ -307,7 +306,8 @@ module Bullet
307
306
  )
308
307
  Bullet::Detector::NPlusOneQuery.call_association(
309
308
  proxy_association.owner,
310
- proxy_association.reflection.name
309
+ proxy_association.reflection.name,
310
+ caller_locations
311
311
  )
312
312
  end
313
313
  super(column_name)
@@ -232,13 +232,13 @@ module Bullet
232
232
 
233
233
  def empty?
234
234
  if Bullet.start? && !reflection.has_cached_counter?
235
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
235
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
236
236
  end
237
237
  super
238
238
  end
239
239
 
240
240
  def include?(object)
241
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
241
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations) if Bullet.start?
242
242
  super
243
243
  end
244
244
  end
@@ -280,11 +280,10 @@ module Bullet
280
280
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
281
281
  Module.new do
282
282
  def empty?
283
- result = super
284
283
  if Bullet.start? && !reflection.has_cached_counter?
285
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
284
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
286
285
  end
287
- result
286
+ super
288
287
  end
289
288
 
290
289
  def count_records
@@ -307,7 +306,8 @@ module Bullet
307
306
  )
308
307
  Bullet::Detector::NPlusOneQuery.call_association(
309
308
  proxy_association.owner,
310
- proxy_association.reflection.name
309
+ proxy_association.reflection.name,
310
+ caller_locations
311
311
  )
312
312
  end
313
313
  super(column_name)
@@ -16,8 +16,8 @@ module Bullet
16
16
  require 'active_record'
17
17
  ::ActiveRecord::Base.extend(
18
18
  Module.new do
19
- def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
20
- result = super
19
+ def find_by_sql(*args, **kwargs, &block)
20
+ result = super(*args, **kwargs, &block)
21
21
  if Bullet.start?
22
22
  if result.is_a? Array
23
23
  if result.size > 1
@@ -114,9 +114,9 @@ module Bullet
114
114
 
115
115
  ::ActiveRecord::Associations::JoinDependency.prepend(
116
116
  Module.new do
117
- def instantiate(result_set, strict_loading_value, &block)
117
+ def instantiate(*args, **kwargs, &block)
118
118
  @bullet_eager_loadings = {}
119
- records = super
119
+ records = super(*args, **kwargs, &block)
120
120
 
121
121
  if Bullet.start?
122
122
  @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
@@ -130,7 +130,8 @@ module Bullet
130
130
  records
131
131
  end
132
132
 
133
- def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
133
+ def construct(*args, **kwargs, &block)
134
+ ar_parent, parent, row = args
134
135
  if Bullet.start?
135
136
  unless ar_parent.nil?
136
137
  parent.children.each do |node|
@@ -153,12 +154,13 @@ module Bullet
153
154
  end
154
155
  end
155
156
 
156
- super
157
+ super(*args, **kwargs, &block)
157
158
  end
158
159
 
159
160
  # call join associations
160
- def construct_model(record, node, row, model_cache, id, strict_loading_value)
161
- result = super
161
+ def construct_model(*args, **kwargs, &block)
162
+ record, node = args
163
+ result = super(*args, **kwargs, &block)
162
164
 
163
165
  if Bullet.start?
164
166
  associations = [node.reflection.name]
@@ -232,13 +234,13 @@ module Bullet
232
234
 
233
235
  def empty?
234
236
  if Bullet.start? && !reflection.has_cached_counter?
235
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
237
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
236
238
  end
237
239
  super
238
240
  end
239
241
 
240
242
  def include?(object)
241
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
243
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations) if Bullet.start?
242
244
  super
243
245
  end
244
246
  end
@@ -280,11 +282,10 @@ module Bullet
280
282
  ::ActiveRecord::Associations::HasManyAssociation.prepend(
281
283
  Module.new do
282
284
  def empty?
283
- result = super
284
285
  if Bullet.start? && !reflection.has_cached_counter?
285
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
286
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name, caller_locations)
286
287
  end
287
- result
288
+ super
288
289
  end
289
290
 
290
291
  def count_records
@@ -307,7 +308,8 @@ module Bullet
307
308
  )
308
309
  Bullet::Detector::NPlusOneQuery.call_association(
309
310
  proxy_association.owner,
310
- proxy_association.reflection.name
311
+ proxy_association.reflection.name,
312
+ caller_locations
311
313
  )
312
314
  end
313
315
  super(column_name)
@@ -13,13 +13,14 @@ module Bullet
13
13
  # first, it keeps this method call for object.association.
14
14
  # then, it checks if this associations call is unpreload.
15
15
  # if it is, keeps this unpreload associations and caller.
16
- def call_association(object, associations)
16
+ def call_association(object, associations, caller_stack = nil)
17
17
  return unless Bullet.start?
18
18
  return unless Bullet.n_plus_one_query_enable?
19
19
  return unless object.bullet_primary_key_value
20
20
  return if inversed_objects.include?(object.bullet_key, associations)
21
21
 
22
22
  add_call_object_associations(object, associations)
23
+ call_stacks.add(object.bullet_key, caller_stack) if caller_stack
23
24
 
24
25
  Bullet.debug(
25
26
  'Detector::NPlusOneQuery#call_association',
@@ -4,8 +4,13 @@ module Bullet
4
4
  module Registry
5
5
  class CallStack < Base
6
6
  # remembers found association backtrace
7
- def add(key)
8
- @registry[key] ||= Thread.current.backtrace
7
+ # if backtrace is provided, it will be used and override any existing value
8
+ def add(key, backtrace = nil)
9
+ if backtrace
10
+ @registry[key] = backtrace
11
+ else
12
+ @registry[key] ||= Thread.current.backtrace
13
+ end
9
14
  end
10
15
  end
11
16
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bullet
4
- VERSION = '8.1.0.beta1'
4
+ VERSION = '8.1.1'
5
5
  end
data/lib/bullet.rb CHANGED
@@ -123,7 +123,7 @@ module Bullet
123
123
  end
124
124
 
125
125
  def get_safelist_associations(type, class_name)
126
- Array.wrap(@safelist[type][class_name])
126
+ Array.wrap(@safelist[type][class_name]).flat_map { |a| [a, a.to_s] }
127
127
  end
128
128
 
129
129
  def reset_safelist
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.1.0.beta1
4
+ version: 8.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
@@ -113,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
113
  - !ruby/object:Gem::Version
114
114
  version: 1.3.6
115
115
  requirements: []
116
- rubygems_version: 3.6.9
116
+ rubygems_version: 4.0.3
117
117
  specification_version: 4
118
118
  summary: help to kill N+1 queries and unused eager loading.
119
119
  test_files: []