bullet 8.1.1 → 8.1.2

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: 4f10d7c7ed8bf9cb6e6b3f0d8d2757bfa71a66d8c4f90da0ce708cfce06eddb8
4
- data.tar.gz: 4986e5b6390339bd6034a598a5f24678dd98c1db907f07de3a2aac1cef4501fd
3
+ metadata.gz: 42ddb49df9a6b4d4176a38561476cda975818bf5861606b4c279af59378a6b1e
4
+ data.tar.gz: 8ae04173fe4f709c39f3a2011403b42617eb91d10de4f25eb29a2a28d06419c3
5
5
  SHA512:
6
- metadata.gz: 323f11d8aee1ba3175eb02795aafb800ad1262f4da84333698fa2f73011b5f9912ad7c38fe37f347ac1b492e90cff87db322433fc6ef55262ab1ecf2e6cc02d7
7
- data.tar.gz: e44277b7412ff505bb3c21047f8eeff5774f367375989192ef27367102eae91f04eb6625f89110160181690ab440051ae6dc2db39d0b5eb89b30fe47a164eab9
6
+ metadata.gz: 990f264d654fb565f413d015aadc0b5dd85ff418f881edf6ca9a50bd8df0a228d101cc7f92c3c2d868eff3c23cbfda3e1fbec554cb05cdb0a275133b984f5ee2
7
+ data.tar.gz: 9f6e68da52ba03e7e434c879baa886d054f18ed5fb0b27606a79094c055f6da0d84702b319c5108812ca71eea94da6d07f07f92dcce31fac889be3858e91a7aa
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## Unreleased
2
+
3
+ ## 8.1.2 (05/25/2026)
4
+
5
+ * Skip N+1 detection for optional polymorphic `belongs_to` whose `*_type` column is nil. ActiveRecord short-circuits the reader to nil without issuing SQL, so the access cannot represent an N+1 query and preloading would be a no-op.
6
+ * Fix `Set#<<` corruption in `UnusedEagerLoading#add_eager_loadings` split branch
7
+
1
8
  ## 8.1.1 (04/23/2026)
2
9
 
3
10
  * Fix ActiveRecord 8.1 patch-level method signature compatibility; test against Rails 8.1.3.
data/README.md CHANGED
@@ -259,6 +259,8 @@ config.after_initialize do
259
259
  end
260
260
  ```
261
261
 
262
+ **Note:** Controller and integration tests work automatically because Bullet's Rack middleware wraps each HTTP request with `Bullet.start_request` and `Bullet.end_request`. However, model tests and other tests that don't go through the Rack middleware (like direct model method calls) require manual wrapping with the test helper code below.
263
+
262
264
  Then wrap each test in the Bullet api.
263
265
 
264
266
  With RSpec:
@@ -19,6 +19,15 @@ module Bullet
19
19
  return unless object.bullet_primary_key_value
20
20
  return if inversed_objects.include?(object.bullet_key, associations)
21
21
 
22
+ # AR short-circuits a polymorphic belongs_to read to nil when the
23
+ # *_type column is nil — no SQL is issued, so this cannot be an N+1.
24
+ # Still record the call so a present preload isn't flagged as unused.
25
+ if optional_polymorphic_belongs_to_with_nil_type?(object, associations)
26
+ add_call_object_associations(object, associations)
27
+ call_stacks.add(object.bullet_key, caller_stack) if caller_stack
28
+ return
29
+ end
30
+
22
31
  add_call_object_associations(object, associations)
23
32
  call_stacks.add(object.bullet_key, caller_stack) if caller_stack
24
33
 
@@ -116,6 +125,19 @@ module Bullet
116
125
 
117
126
  private
118
127
 
128
+ def optional_polymorphic_belongs_to_with_nil_type?(object, associations)
129
+ return false unless associations.is_a?(Symbol) || associations.is_a?(String)
130
+ return false unless object.class.respond_to?(:reflect_on_association)
131
+
132
+ reflection = object.class.reflect_on_association(associations.to_sym)
133
+ return false unless reflection
134
+ return false unless reflection.respond_to?(:polymorphic?) && reflection.polymorphic?
135
+ return false unless reflection.respond_to?(:foreign_type)
136
+
137
+ foreign_type = reflection.foreign_type
138
+ foreign_type && object.respond_to?(:[]) && object[foreign_type].nil?
139
+ end
140
+
119
141
  def create_notification(callers, klazz, associations)
120
142
  notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:n_plus_one_query, klazz)
121
143
 
@@ -50,7 +50,7 @@ module Bullet
50
50
  if key_objects_overlap == k
51
51
  to_add << [k, associations]
52
52
  else
53
- to_merge << [key_objects_overlap, (eager_loadings[k].dup << associations)]
53
+ to_merge << [key_objects_overlap, eager_loadings[k].dup.merge(Array.wrap(associations))]
54
54
 
55
55
  keys_without_objects = k - key_objects_overlap
56
56
  to_merge << [keys_without_objects, eager_loadings[k]]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bullet
4
- VERSION = '8.1.1'
4
+ VERSION = '8.1.2'
5
5
  end
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.1
4
+ version: 8.1.2
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: 4.0.3
116
+ rubygems_version: 4.0.6
117
117
  specification_version: 4
118
118
  summary: help to kill N+1 queries and unused eager loading.
119
119
  test_files: []