bullet 7.0.3 → 7.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +7 -2
  5. data/lib/bullet/active_record4.rb +9 -0
  6. data/lib/bullet/active_record41.rb +9 -0
  7. data/lib/bullet/active_record42.rb +9 -0
  8. data/lib/bullet/active_record5.rb +24 -8
  9. data/lib/bullet/active_record52.rb +23 -7
  10. data/lib/bullet/active_record60.rb +22 -6
  11. data/lib/bullet/active_record61.rb +22 -6
  12. data/lib/bullet/active_record70.rb +43 -14
  13. data/lib/bullet/active_record71.rb +304 -0
  14. data/lib/bullet/dependency.rb +12 -0
  15. data/lib/bullet/detector/association.rb +8 -0
  16. data/lib/bullet/detector/n_plus_one_query.rb +17 -9
  17. data/lib/bullet/detector/unused_eager_loading.rb +6 -3
  18. data/lib/bullet/ext/object.rb +13 -3
  19. data/lib/bullet/mongoid7x.rb +8 -10
  20. data/lib/bullet/mongoid8x.rb +59 -0
  21. data/lib/bullet/notification/base.rb +9 -8
  22. data/lib/bullet/notification/counter_cache.rb +1 -1
  23. data/lib/bullet/rack.rb +41 -7
  24. data/lib/bullet/registry/association.rb +2 -1
  25. data/lib/bullet/registry/call_stack.rb +12 -0
  26. data/lib/bullet/registry.rb +1 -0
  27. data/lib/bullet/stack_trace_filter.rb +13 -10
  28. data/lib/bullet/version.rb +1 -1
  29. data/lib/bullet.rb +13 -3
  30. metadata +8 -153
  31. data/.github/workflows/main.yml +0 -82
  32. data/.gitignore +0 -15
  33. data/.rspec +0 -2
  34. data/Gemfile +0 -24
  35. data/Gemfile.mongoid +0 -12
  36. data/Gemfile.mongoid-4.0 +0 -15
  37. data/Gemfile.mongoid-5.0 +0 -15
  38. data/Gemfile.mongoid-6.0 +0 -15
  39. data/Gemfile.mongoid-7.0 +0 -15
  40. data/Gemfile.rails-4.0 +0 -16
  41. data/Gemfile.rails-4.1 +0 -16
  42. data/Gemfile.rails-4.2 +0 -16
  43. data/Gemfile.rails-5.0 +0 -15
  44. data/Gemfile.rails-5.1 +0 -15
  45. data/Gemfile.rails-5.2 +0 -15
  46. data/Gemfile.rails-6.0 +0 -15
  47. data/Gemfile.rails-6.1 +0 -15
  48. data/Gemfile.rails-7.0 +0 -10
  49. data/Guardfile +0 -8
  50. data/Hacking.md +0 -75
  51. data/Rakefile +0 -51
  52. data/bullet.gemspec +0 -33
  53. data/perf/benchmark.rb +0 -118
  54. data/rails/init.rb +0 -3
  55. data/spec/bullet/detector/association_spec.rb +0 -28
  56. data/spec/bullet/detector/base_spec.rb +0 -10
  57. data/spec/bullet/detector/counter_cache_spec.rb +0 -58
  58. data/spec/bullet/detector/n_plus_one_query_spec.rb +0 -182
  59. data/spec/bullet/detector/unused_eager_loading_spec.rb +0 -121
  60. data/spec/bullet/ext/object_spec.rb +0 -44
  61. data/spec/bullet/ext/string_spec.rb +0 -15
  62. data/spec/bullet/notification/base_spec.rb +0 -94
  63. data/spec/bullet/notification/counter_cache_spec.rb +0 -14
  64. data/spec/bullet/notification/n_plus_one_query_spec.rb +0 -29
  65. data/spec/bullet/notification/unused_eager_loading_spec.rb +0 -18
  66. data/spec/bullet/notification_collector_spec.rb +0 -34
  67. data/spec/bullet/rack_spec.rb +0 -279
  68. data/spec/bullet/registry/association_spec.rb +0 -28
  69. data/spec/bullet/registry/base_spec.rb +0 -46
  70. data/spec/bullet/registry/object_spec.rb +0 -26
  71. data/spec/bullet_spec.rb +0 -136
  72. data/spec/integration/active_record/association_spec.rb +0 -793
  73. data/spec/integration/counter_cache_spec.rb +0 -68
  74. data/spec/integration/mongoid/association_spec.rb +0 -246
  75. data/spec/models/address.rb +0 -5
  76. data/spec/models/attachment.rb +0 -5
  77. data/spec/models/author.rb +0 -5
  78. data/spec/models/base_user.rb +0 -7
  79. data/spec/models/category.rb +0 -12
  80. data/spec/models/city.rb +0 -5
  81. data/spec/models/client.rb +0 -8
  82. data/spec/models/comment.rb +0 -8
  83. data/spec/models/company.rb +0 -5
  84. data/spec/models/country.rb +0 -5
  85. data/spec/models/deal.rb +0 -5
  86. data/spec/models/document.rb +0 -7
  87. data/spec/models/entry.rb +0 -5
  88. data/spec/models/firm.rb +0 -7
  89. data/spec/models/folder.rb +0 -4
  90. data/spec/models/group.rb +0 -4
  91. data/spec/models/mongoid/address.rb +0 -9
  92. data/spec/models/mongoid/category.rb +0 -10
  93. data/spec/models/mongoid/comment.rb +0 -9
  94. data/spec/models/mongoid/company.rb +0 -9
  95. data/spec/models/mongoid/entry.rb +0 -9
  96. data/spec/models/mongoid/post.rb +0 -14
  97. data/spec/models/mongoid/user.rb +0 -7
  98. data/spec/models/newspaper.rb +0 -5
  99. data/spec/models/page.rb +0 -4
  100. data/spec/models/person.rb +0 -5
  101. data/spec/models/pet.rb +0 -5
  102. data/spec/models/post.rb +0 -34
  103. data/spec/models/relationship.rb +0 -6
  104. data/spec/models/reply.rb +0 -5
  105. data/spec/models/role.rb +0 -7
  106. data/spec/models/student.rb +0 -5
  107. data/spec/models/submission.rb +0 -7
  108. data/spec/models/teacher.rb +0 -5
  109. data/spec/models/user.rb +0 -8
  110. data/spec/models/writer.rb +0 -4
  111. data/spec/spec_helper.rb +0 -97
  112. data/spec/support/bullet_ext.rb +0 -56
  113. data/spec/support/mongo_seed.rb +0 -59
  114. data/spec/support/rack_double.rb +0 -49
  115. data/spec/support/sqlite_seed.rb +0 -284
  116. data/test.sh +0 -15
  117. data/update.sh +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ad1f81292cc89778a41c6dd178bbfb6342fe1b69c4e57c3fdad0d8003d97b525
4
- data.tar.gz: 5c1c8113f6e03ecdb449bce5e12273b969f29c323a5bb802c13c0539ea439a69
3
+ metadata.gz: 7c62bb5eb8bdfdb62ce49a79609ce7665d6af8be0f7dede7361379597415dcd4
4
+ data.tar.gz: 8da00673c07b79eb6dbf7b061aaf6dd0208fd0be841a96c3169ba919259fcf82
5
5
  SHA512:
6
- metadata.gz: 1f0d4d73910f96ab8c6ae5b6b1bc58de547c2c32a7c689c2984778465dae29d2c2cae81c23699b3848d2eaef30223db66bcca6ccb421b9078d5616f497421d45
7
- data.tar.gz: 3b9001966918da22bfe7b2960526ac0db471a75e79e7939b099bebe3dde1fb27ea69b1afbdec0fcc98a6cb4260b845b5551a1a07cec036207c885be4e14ef7b9
6
+ metadata.gz: f33ad269a72ba293680c65ed460ef4e598446eebf62c82d79879de03b3cb52098f27499cab681facec3fdc3a3d6f937d064c21621aefcc69edcf499a52680838
7
+ data.tar.gz: 4a386c2bda2cdea90926ce9ff8bca0932954507ac4fa1e5986a356d869c3fb410b48708a5de843fb0e1f822f744ef1cf26dcecc9036ad3036f774ffad1c6e84e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  ## Next Release
2
2
 
3
+ ## 7.1.2 (10/13/2023)
4
+
5
+ * Handle Rails 7.1 composite primary keys
6
+
7
+ ## 7.1.1 (10/07/2023)
8
+
9
+ * Add support for `Content-Security-Policy-Report-Only` nonces
10
+ * Fix count method signature
11
+
12
+ ## 7.1.0 (10/06/2023)
13
+
14
+ * Support rails 7.1
15
+ * Alias `Bullet.enable?` to `enabled?`, and `Bullet.enable=` to `enabled=`
16
+ * Added `always_append_html_body` option, so the html snippet is always included even if there are no notifications
17
+ * Added detection of n+1 count queries from `count` method
18
+ * Changed the counter cache notification title to recommend using `size`
19
+
20
+ ## 7.0.7 (03/01/2023)
21
+
22
+ * Check `Rails.application.config.content_security_policy` before insert `Bullet::Rack`
23
+
24
+ ## 7.0.6 (03/01/2023)
25
+
26
+ * Better way to check if `ActionDispatch::ContentSecurityPolicy::Middleware` exists
27
+
28
+ ## 7.0.5 (01/01/2023)
29
+
30
+ * Fix n+1 false positives in AR 7.0
31
+ * Fix eager_load nested has_many :through false positives
32
+ * Respect Content-Security-Policy nonces
33
+ * Added CallStacks support for avoid eager loading
34
+ * Iterate fewer times over objects
35
+
36
+ ## 7.0.4 (11/28/2022)
37
+
38
+ * Fix `eager_load` `has_many :through` false positives
39
+ * mongoid7x: add dynamic methods
40
+
3
41
  ## 7.0.3 (08/13/2022)
4
42
 
5
43
  * Replace `Array()` with `Array.wrap()`
@@ -76,7 +114,7 @@
76
114
 
77
115
  * Fix through reflection for rails 5.x
78
116
  * Fix false positive in after_save/after_create callbacks
79
- * Don't triger a preload error on "manual" preloads
117
+ * Don't trigger a preload error on "manual" preloads
80
118
  * Avoid Bullet from making extra queries in mongoid6
81
119
  * Support option for #first and #last on mongoid6.x
82
120
  * Fix duplicate logs in mongoid 4.x and 5.x version
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 - 2010 Richard Huang (flyerhzm@gmail.com)
1
+ Copyright (c) 2009 - 2022 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
@@ -101,6 +101,7 @@ The code above will enable all of the Bullet notification systems:
101
101
  item is a line number, a Range of line numbers, or a (bare) method name, to exclude only particular lines in a file.
102
102
  * `Bullet.slack`: add notifications to slack
103
103
  * `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
104
+ * `Bullet.always_append_html_body`: always append the html body even if no notifications are present. Note: `console` or `add_footer` must also be true. Useful for Single Page Applications where the initial page load might not have any notifications present.
104
105
 
105
106
 
106
107
  Bullet also allows you to disable any of its detectors.
@@ -119,6 +120,8 @@ Bullet.unused_eager_loading_enable = false
119
120
  Bullet.counter_cache_enable = false
120
121
  ```
121
122
 
123
+ Note: When calling `Bullet.enable`, all other detectors are reset to their defaults (`true`) and need reconfiguring.
124
+
122
125
  ## Safe list
123
126
 
124
127
  Sometimes Bullet may notify you of query problems you don't care to fix, or
@@ -222,7 +225,7 @@ end
222
225
 
223
226
  ### Work with sinatra
224
227
 
225
- Configure and use `Bullet::Rack`
228
+ Configure and use `Bullet::Rack`.
226
229
 
227
230
  ```ruby
228
231
  configure :development do
@@ -232,6 +235,8 @@ configure :development do
232
235
  end
233
236
  ```
234
237
 
238
+ If your application generates a Content-Security-Policy via a separate middleware, ensure that `Bullet::Rack` is loaded _before_ that middleware.
239
+
235
240
  ### Run in tests
236
241
 
237
242
  First you need to enable Bullet in test environment.
@@ -285,7 +290,7 @@ $ rails g scaffold comment name:string post_id:integer
285
290
  $ bundle exec rake db:migrate
286
291
  ```
287
292
 
288
- 2\. Change `app/model/post.rb` and `app/model/comment.rb`
293
+ 2\. Change `app/models/post.rb` and `app/models/comment.rb`
289
294
 
290
295
  ```ruby
291
296
  class Post < ActiveRecord::Base
@@ -176,6 +176,15 @@ module Bullet
176
176
  result
177
177
  end
178
178
  end
179
+
180
+ ::ActiveRecord::Associations::CollectionProxy.class_eval do
181
+ def count(column_name = nil, options = {})
182
+ if Bullet.start?
183
+ Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
184
+ end
185
+ super(column_name, options)
186
+ end
187
+ end
179
188
  end
180
189
  end
181
190
  end
@@ -168,6 +168,15 @@ module Bullet
168
168
  origin_count_records
169
169
  end
170
170
  end
171
+
172
+ ::ActiveRecord::Associations::CollectionProxy.class_eval do
173
+ def count(column_name = nil, options = {})
174
+ if Bullet.start?
175
+ Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
176
+ end
177
+ super(column_name, options)
178
+ end
179
+ end
171
180
  end
172
181
  end
173
182
  end
@@ -233,6 +233,15 @@ module Bullet
233
233
  origin_count_records
234
234
  end
235
235
  end
236
+
237
+ ::ActiveRecord::Associations::CollectionProxy.class_eval do
238
+ def count(column_name = nil, options = {})
239
+ if Bullet.start?
240
+ Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
241
+ end
242
+ super(column_name, options)
243
+ end
244
+ end
236
245
  end
237
246
  end
238
247
  end
@@ -177,16 +177,18 @@ module Bullet
177
177
  if Bullet.start?
178
178
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
179
179
  refl = reflection.through_reflection
180
- Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
181
- association = owner.association refl.name
182
- Array.wrap(association.target).each do |through_record|
183
- Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
184
- end
180
+ association = owner.association(refl.name)
181
+ if association.loaded?
182
+ Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
183
+ Array.wrap(association.target).each do |through_record|
184
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
185
+ end
185
186
 
186
- if refl.through_reflection?
187
- refl = refl.through_reflection while refl.through_reflection?
187
+ if refl.through_reflection?
188
+ refl = refl.through_reflection while refl.through_reflection?
188
189
 
189
- Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
190
+ Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
191
+ end
190
192
  end
191
193
  end
192
194
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
@@ -258,6 +260,20 @@ module Bullet
258
260
  end
259
261
  end
260
262
  )
263
+
264
+ ::ActiveRecord::Associations::CollectionProxy.prepend(
265
+ Module.new do
266
+ def count
267
+ if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
268
+ Bullet::Detector::CounterCache.add_counter_cache(
269
+ proxy_association.owner,
270
+ proxy_association.reflection.name
271
+ )
272
+ end
273
+ super
274
+ end
275
+ end
276
+ )
261
277
  end
262
278
  end
263
279
  end
@@ -150,14 +150,16 @@ module Bullet
150
150
 
151
151
  if Bullet.start?
152
152
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
153
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
154
- association = owner.association reflection.through_reflection.name
155
- Array.wrap(association.target).each do |through_record|
156
- Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
157
- end
153
+ association = owner.association(reflection.through_reflection.name)
154
+ if association.loaded?
155
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
156
+ Array.wrap(association.target).each do |through_record|
157
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
158
+ end
158
159
 
159
- if reflection.through_reflection != through_reflection
160
- Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
160
+ if reflection.through_reflection != through_reflection
161
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
162
+ end
161
163
  end
162
164
  end
163
165
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
@@ -240,6 +242,20 @@ module Bullet
240
242
  end
241
243
  end
242
244
  )
245
+
246
+ ::ActiveRecord::Associations::CollectionProxy.prepend(
247
+ Module.new do
248
+ def count(column_name = nil)
249
+ if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
250
+ Bullet::Detector::CounterCache.add_counter_cache(
251
+ proxy_association.owner,
252
+ proxy_association.reflection.name
253
+ )
254
+ end
255
+ super(column_name)
256
+ end
257
+ end
258
+ )
243
259
  end
244
260
  end
245
261
  end
@@ -177,14 +177,16 @@ module Bullet
177
177
 
178
178
  if Bullet.start?
179
179
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
180
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
181
180
  association = owner.association(reflection.through_reflection.name)
182
- Array.wrap(association.target).each do |through_record|
183
- Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
184
- end
181
+ if association.loaded?
182
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
183
+ Array.wrap(association.target).each do |through_record|
184
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
185
+ end
185
186
 
186
- if reflection.through_reflection != through_reflection
187
- Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
187
+ if reflection.through_reflection != through_reflection
188
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
189
+ end
188
190
  end
189
191
  end
190
192
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
@@ -267,6 +269,20 @@ module Bullet
267
269
  end
268
270
  end
269
271
  )
272
+
273
+ ::ActiveRecord::Associations::CollectionProxy.prepend(
274
+ Module.new do
275
+ def count
276
+ if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
277
+ Bullet::Detector::CounterCache.add_counter_cache(
278
+ proxy_association.owner,
279
+ proxy_association.reflection.name
280
+ )
281
+ end
282
+ super
283
+ end
284
+ end
285
+ )
270
286
  end
271
287
  end
272
288
  end
@@ -177,14 +177,16 @@ module Bullet
177
177
 
178
178
  if Bullet.start?
179
179
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
180
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
181
180
  association = owner.association(reflection.through_reflection.name)
182
- Array.wrap(association.target).each do |through_record|
183
- Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
184
- end
181
+ if association.loaded?
182
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
183
+ Array.wrap(association.target).each do |through_record|
184
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
185
+ end
185
186
 
186
- if reflection.through_reflection != through_reflection
187
- Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
187
+ if reflection.through_reflection != through_reflection
188
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
189
+ end
188
190
  end
189
191
  end
190
192
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
@@ -267,6 +269,20 @@ module Bullet
267
269
  end
268
270
  end
269
271
  )
272
+
273
+ ::ActiveRecord::Associations::CollectionProxy.prepend(
274
+ Module.new do
275
+ def count(column_name = nil)
276
+ if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
277
+ Bullet::Detector::CounterCache.add_counter_cache(
278
+ proxy_association.owner,
279
+ proxy_association.reflection.name
280
+ )
281
+ end
282
+ super(column_name)
283
+ end
284
+ end
285
+ )
270
286
  end
271
287
  end
272
288
  end
@@ -65,7 +65,9 @@ module Bullet
65
65
  def call
66
66
  if Bullet.start?
67
67
  @preloaders.each do |preloader|
68
- preloader.records.each { |record| Bullet::Detector::Association.add_object_associations(record, preloader.associations) }
68
+ preloader.records.each { |record|
69
+ Bullet::Detector::Association.add_object_associations(record, preloader.associations)
70
+ }
69
71
  Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
70
72
  end
71
73
  end
@@ -80,7 +82,9 @@ module Bullet
80
82
  if Bullet.start?
81
83
  reflection_records.compact!
82
84
  if reflection_records.first.class.name !~ /^HABTM_/
83
- reflection_records.each { |record| Bullet::Detector::Association.add_object_associations(record, reflection.name) }
85
+ reflection_records.each { |record|
86
+ Bullet::Detector::Association.add_object_associations(record, reflection.name)
87
+ }
84
88
  Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
85
89
  end
86
90
  end
@@ -91,16 +95,18 @@ module Bullet
91
95
 
92
96
  ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
93
97
  Module.new do
94
- def preloaded_records
95
- if Bullet.start? && !defined?(@preloaded_records)
96
- source_preloaders.each do |source_preloader|
97
- reflection_name = source_preloader.send(:reflection).name
98
- source_preloader.send(:owners).each do |owner|
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|
99
104
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
100
105
  end
101
106
  end
107
+ else
108
+ super
102
109
  end
103
- super
104
110
  end
105
111
  end
106
112
  )
@@ -170,6 +176,13 @@ module Bullet
170
176
  end
171
177
  super
172
178
  end
179
+
180
+ def inversed_from_queries(record)
181
+ if Bullet.start? && inversable?(record)
182
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
183
+ end
184
+ super
185
+ end
173
186
  end
174
187
  )
175
188
 
@@ -180,14 +193,16 @@ module Bullet
180
193
 
181
194
  if Bullet.start?
182
195
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
183
- Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
184
196
  association = owner.association(reflection.through_reflection.name)
185
- Array.wrap(association.target).each do |through_record|
186
- Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
187
- end
197
+ if association.loaded?
198
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
199
+ Array.wrap(association.target).each do |through_record|
200
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
201
+ end
188
202
 
189
- if reflection.through_reflection != through_reflection
190
- Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
203
+ if reflection.through_reflection != through_reflection
204
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
205
+ end
191
206
  end
192
207
  end
193
208
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
@@ -270,6 +285,20 @@ module Bullet
270
285
  end
271
286
  end
272
287
  )
288
+
289
+ ::ActiveRecord::Associations::CollectionProxy.prepend(
290
+ Module.new do
291
+ def count(column_name = nil)
292
+ if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
293
+ Bullet::Detector::CounterCache.add_counter_cache(
294
+ proxy_association.owner,
295
+ proxy_association.reflection.name
296
+ )
297
+ end
298
+ super(column_name)
299
+ end
300
+ end
301
+ )
273
302
  end
274
303
  end
275
304
  end