bullet 4.13.1 → 5.0.0

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +57 -1
  3. data/CHANGELOG.md +57 -2
  4. data/Gemfile.mongoid +0 -2
  5. data/Gemfile.mongoid-2.4 +2 -4
  6. data/Gemfile.mongoid-2.5 +2 -4
  7. data/Gemfile.mongoid-2.6 +1 -3
  8. data/Gemfile.mongoid-2.7 +2 -4
  9. data/Gemfile.mongoid-2.8 +2 -4
  10. data/Gemfile.mongoid-3.0 +2 -4
  11. data/Gemfile.mongoid-3.1 +2 -4
  12. data/Gemfile.mongoid-4.0 +1 -3
  13. data/Gemfile.mongoid-5.0 +17 -0
  14. data/Gemfile.rails-3.0 +1 -3
  15. data/Gemfile.rails-3.1 +1 -3
  16. data/Gemfile.rails-3.2 +1 -3
  17. data/Gemfile.rails-4.0 +1 -3
  18. data/Gemfile.rails-4.1 +1 -3
  19. data/Gemfile.rails-4.2 +17 -0
  20. data/Gemfile.rails-5.0 +17 -0
  21. data/README.md +31 -2
  22. data/bullet.gemspec +1 -1
  23. data/lib/bullet/active_record3.rb +65 -35
  24. data/lib/bullet/active_record3x.rb +54 -32
  25. data/lib/bullet/active_record4.rb +62 -30
  26. data/lib/bullet/active_record41.rb +63 -32
  27. data/lib/bullet/active_record42.rb +214 -0
  28. data/lib/bullet/active_record5.rb +217 -0
  29. data/lib/bullet/dependency.rb +22 -0
  30. data/lib/bullet/detector/association.rb +16 -16
  31. data/lib/bullet/detector/counter_cache.rb +13 -13
  32. data/lib/bullet/detector/n_plus_one_query.rb +33 -24
  33. data/lib/bullet/detector/unused_eager_loading.rb +2 -2
  34. data/lib/bullet/ext/object.rb +4 -2
  35. data/lib/bullet/mongoid5x.rb +56 -0
  36. data/lib/bullet/notification/base.rb +7 -11
  37. data/lib/bullet/notification/n_plus_one_query.rb +6 -4
  38. data/lib/bullet/rack.rb +20 -13
  39. data/lib/bullet/version.rb +1 -1
  40. data/lib/bullet.rb +29 -12
  41. data/spec/bullet/detector/counter_cache_spec.rb +8 -8
  42. data/spec/bullet/detector/n_plus_one_query_spec.rb +42 -27
  43. data/spec/bullet/ext/object_spec.rb +6 -0
  44. data/spec/bullet/notification/base_spec.rb +4 -29
  45. data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -3
  46. data/spec/bullet/notification/unused_eager_loading_spec.rb +1 -1
  47. data/spec/bullet/rack_spec.rb +3 -3
  48. data/spec/bullet_spec.rb +47 -0
  49. data/spec/integration/active_record3/association_spec.rb +11 -2
  50. data/spec/integration/active_record4/association_spec.rb +58 -3
  51. data/spec/integration/active_record5/association_spec.rb +715 -0
  52. data/spec/integration/counter_cache_spec.rb +17 -1
  53. data/spec/models/category.rb +4 -1
  54. data/spec/models/comment.rb +2 -0
  55. data/spec/models/post.rb +7 -2
  56. data/spec/models/reply.rb +3 -0
  57. data/spec/models/submission.rb +1 -1
  58. data/spec/spec_helper.rb +3 -2
  59. data/spec/support/mongo_seed.rb +13 -0
  60. data/spec/support/sqlite_seed.rb +14 -6
  61. data/test.sh +2 -0
  62. data/update.sh +15 -0
  63. metadata +18 -7
@@ -0,0 +1,715 @@
1
+ require 'spec_helper'
2
+
3
+ if !mongoid? && active_record5?
4
+ describe Bullet::Detector::Association, 'has_many' do
5
+ context "post => comments" do
6
+ it "should detect non preload post => comments" do
7
+ Post.all.each do |post|
8
+ post.comments.map(&:name)
9
+ end
10
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
11
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
12
+
13
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
14
+ end
15
+
16
+ it "should detect preload with post => comments" do
17
+ Post.includes(:comments).each do |post|
18
+ post.comments.map(&:name)
19
+ end
20
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
21
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
22
+
23
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
24
+ end
25
+
26
+ it "should detect unused preload post => comments" do
27
+ Post.includes(:comments).map(&:name)
28
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
29
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
30
+
31
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
32
+ end
33
+
34
+ it "should not detect unused preload post => comments" do
35
+ Post.all.map(&:name)
36
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
37
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
38
+
39
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
40
+ end
41
+
42
+ it "should detect non preload comment => post with inverse_of" do
43
+ Post.includes(:comments).each do |post|
44
+ post.comments.each do |comment|
45
+ comment.name
46
+ comment.post.name
47
+ end
48
+ end
49
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
50
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
51
+
52
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
53
+ end
54
+
55
+ it "should detect non preload post => comments with empty?" do
56
+ Post.all.each do |post|
57
+ post.comments.empty?
58
+ end
59
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
60
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
61
+
62
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
63
+ end
64
+
65
+ it "should detect non preload post => comments with include?" do
66
+ comment = Comment.last
67
+ Post.all.each do |post|
68
+ post.comments.include?(comment)
69
+ end
70
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
71
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
72
+
73
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
74
+ end
75
+ end
76
+
77
+ context "category => posts => comments" do
78
+ it "should detect non preload category => posts => comments" do
79
+ Category.all.each do |category|
80
+ category.posts.each do |post|
81
+ post.comments.map(&:name)
82
+ end
83
+ end
84
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
85
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
86
+
87
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :posts)
88
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
89
+ end
90
+
91
+ it "should detect preload category => posts, but no post => comments" do
92
+ Category.includes(:posts).each do |category|
93
+ category.posts.each do |post|
94
+ post.comments.map(&:name)
95
+ end
96
+ end
97
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
98
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
99
+
100
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Category, :posts)
101
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
102
+ end
103
+
104
+ it "should detect preload with category => posts => comments" do
105
+ Category.includes({:posts => :comments}).each do |category|
106
+ category.posts.each do |post|
107
+ post.comments.map(&:name)
108
+ end
109
+ end
110
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
111
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
112
+
113
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
114
+ end
115
+
116
+ it "should detect preload with category => posts => comments with posts.id > 0" do
117
+ Category.includes({:posts => :comments}).where('posts.id > 0').references(:posts).each do |category|
118
+ category.posts.each do |post|
119
+ post.comments.map(&:name)
120
+ end
121
+ end
122
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
123
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
124
+
125
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
126
+ end
127
+
128
+ it "should detect unused preload with category => posts => comments" do
129
+ Category.includes({:posts => :comments}).map(&:name)
130
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
131
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
132
+
133
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
134
+ end
135
+
136
+ it "should detect unused preload with post => commnets, no category => posts" do
137
+ Category.includes({:posts => :comments}).each do |category|
138
+ category.posts.map(&:name)
139
+ end
140
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
141
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
142
+
143
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
144
+ end
145
+ end
146
+
147
+ context "category => posts, category => entries" do
148
+ it "should detect non preload with category => [posts, entries]" do
149
+ Category.all.each do |category|
150
+ category.posts.map(&:name)
151
+ category.entries.map(&:name)
152
+ end
153
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
154
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
155
+
156
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :posts)
157
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :entries)
158
+ end
159
+
160
+ it "should detect preload with category => posts, but not with category => entries" do
161
+ Category.includes(:posts).each do |category|
162
+ category.posts.map(&:name)
163
+ category.entries.map(&:name)
164
+ end
165
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
166
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
167
+
168
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Category, :posts)
169
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :entries)
170
+ end
171
+
172
+ it "should detect preload with category => [posts, entries]" do
173
+ Category.includes([:posts, :entries]).each do |category|
174
+ category.posts.map(&:name)
175
+ category.entries.map(&:name)
176
+ end
177
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
178
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
179
+
180
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
181
+ end
182
+
183
+ it "should detect unused preload with category => [posts, entries]" do
184
+ Category.includes([:posts, :entries]).map(&:name)
185
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
186
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :posts)
187
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :entries)
188
+
189
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
190
+ end
191
+
192
+ it "should detect unused preload with category => entries, but not with category => posts" do
193
+ Category.includes([:posts, :entries]).each do |category|
194
+ category.posts.map(&:name)
195
+ end
196
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
197
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Category, :posts)
198
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :entries)
199
+
200
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
201
+ end
202
+ end
203
+
204
+ context "post => comment" do
205
+ it "should detect unused preload with post => comments" do
206
+ Post.includes(:comments).each do |post|
207
+ post.comments.first.name
208
+ end
209
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
210
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :comments)
211
+
212
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
213
+ end
214
+
215
+ it "should detect preload with post => commnets" do
216
+ Post.first.comments.map(&:name)
217
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
218
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
219
+
220
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
221
+ end
222
+
223
+ it "should not detect unused preload with category => posts" do
224
+ category = Category.first
225
+ category.draft_post.destroy!
226
+ post = category.draft_post
227
+ post.update_attributes!(link: true)
228
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
229
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
230
+
231
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
232
+
233
+ Support::SqliteSeed.setup_db
234
+ Support::SqliteSeed.seed_db
235
+ end
236
+ end
237
+
238
+ context "category => posts => writer" do
239
+ it "should not detect unused preload associations" do
240
+ category = Category.includes({:posts => :writer}).order("id DESC").find_by_name('first')
241
+ category.posts.map do |post|
242
+ post.name
243
+ post.writer.name
244
+ end
245
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
246
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Category, :posts)
247
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :writer)
248
+ end
249
+ end
250
+
251
+ context "scope for_category_name" do
252
+ it "should detect preload with post => category" do
253
+ Post.in_category_name('first').references(:categories).each do |post|
254
+ post.category.name
255
+ end
256
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
257
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
258
+
259
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
260
+ end
261
+
262
+ it "should not be unused preload post => category" do
263
+ Post.in_category_name('first').references(:categories).map(&:name)
264
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
265
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
266
+
267
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
268
+ end
269
+ end
270
+
271
+ context "scope preload_comments" do
272
+ it "should detect preload post => comments with scope" do
273
+ Post.preload_comments.each do |post|
274
+ post.comments.map(&:name)
275
+ end
276
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
277
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
278
+
279
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
280
+ end
281
+
282
+ it "should detect unused preload with scope" do
283
+ Post.preload_comments.map(&:name)
284
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
285
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
286
+
287
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
288
+ end
289
+ end
290
+ end
291
+
292
+ describe Bullet::Detector::Association, 'belongs_to' do
293
+ context "comment => post" do
294
+ it "should detect non preload with comment => post" do
295
+ Comment.all.each do |comment|
296
+ comment.post.name
297
+ end
298
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
299
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
300
+
301
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
302
+ end
303
+
304
+ it "should detect preload with one comment => post" do
305
+ Comment.first.post.name
306
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
307
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
308
+
309
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
310
+ end
311
+
312
+ it "should dtect preload with comment => post" do
313
+ Comment.includes(:post).each do |comment|
314
+ comment.post.name
315
+ end
316
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
317
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
318
+
319
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
320
+ end
321
+
322
+ it "should not detect preload with comment => post" do
323
+ Comment.all.map(&:name)
324
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
325
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
326
+
327
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
328
+ end
329
+
330
+ it "should detect unused preload with comment => post" do
331
+ Comment.includes(:post).map(&:name)
332
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
333
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Comment, :post)
334
+
335
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
336
+ end
337
+ end
338
+
339
+ context "comment => post => category" do
340
+ it "should detect non preload association with comment => post" do
341
+ Comment.all.each do |comment|
342
+ comment.post.category.name
343
+ end
344
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
345
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
346
+
347
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
348
+ end
349
+
350
+ it "should not detect non preload association with only one comment" do
351
+ Comment.first.post.category.name
352
+
353
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
354
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
355
+
356
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
357
+ end
358
+
359
+ it "should detect non preload association with post => category" do
360
+ Comment.includes(:post).each do |comment|
361
+ comment.post.category.name
362
+ end
363
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
364
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
365
+
366
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :category)
367
+ end
368
+
369
+ it "should not detect unpreload association" do
370
+ Comment.includes(:post => :category).each do |comment|
371
+ comment.post.category.name
372
+ end
373
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
374
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
375
+
376
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
377
+ end
378
+ end
379
+
380
+ context "comment => author, post => writer" do
381
+ it "should detect non preloaded writer" do
382
+ Comment.includes([:author, :post]).where(["base_users.id = ?", BaseUser.first]).references(:base_users).each do |comment|
383
+ comment.post.writer.name
384
+ end
385
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
386
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
387
+
388
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :writer)
389
+ end
390
+
391
+ it "should detect unused preload with comment => author" do
392
+ Comment.includes([:author, {:post => :writer}]).where(["base_users.id = ?", BaseUser.first]).references(:base_users).each do |comment|
393
+ comment.post.writer.name
394
+ end
395
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
396
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
397
+
398
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
399
+ end
400
+
401
+ it "should detect non preloading with writer => newspaper" do
402
+ Comment.includes(:post => :writer).where("posts.name like '%first%'").references(:posts).each do |comment|
403
+ comment.post.writer.newspaper.name
404
+ end
405
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
406
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
407
+
408
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Writer, :newspaper)
409
+ end
410
+
411
+ it "should not raise a stack error from posts to category" do
412
+ expect {
413
+ Comment.includes({:post => :category}).each do |com|
414
+ com.post.category
415
+ end
416
+ }.not_to raise_error()
417
+ end
418
+ end
419
+ end
420
+
421
+ describe Bullet::Detector::Association, 'has_and_belongs_to_many' do
422
+ context "students <=> teachers" do
423
+ it "should detect non preload associations" do
424
+ Student.all.each do |student|
425
+ student.teachers.map(&:name)
426
+ end
427
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
428
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
429
+
430
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Student, :teachers)
431
+ end
432
+
433
+ it "should detect preload associations" do
434
+ Student.includes(:teachers).each do |student|
435
+ student.teachers.map(&:name)
436
+ end
437
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
438
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
439
+
440
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
441
+ end
442
+
443
+ it "should detect unused preload associations" do
444
+ Student.includes(:teachers).map(&:name)
445
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
446
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Student, :teachers)
447
+
448
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
449
+ end
450
+
451
+ it "should detect no unused preload associations" do
452
+ Student.all.map(&:name)
453
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
454
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
455
+
456
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
457
+ end
458
+ end
459
+ end
460
+
461
+ describe Bullet::Detector::Association, 'has_many :through' do
462
+ context "firm => clients" do
463
+ it "should detect non preload associations" do
464
+ Firm.all.each do |firm|
465
+ firm.clients.map(&:name)
466
+ end
467
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
468
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
469
+
470
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Firm, :clients)
471
+ end
472
+
473
+ it "should detect preload associations" do
474
+ Firm.includes(:clients).each do |firm|
475
+ firm.clients.map(&:name)
476
+ end
477
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
478
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
479
+
480
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
481
+ end
482
+
483
+ it "should not detect preload associations" do
484
+ Firm.all.map(&:name)
485
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
486
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
487
+
488
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
489
+ end
490
+
491
+ it "should detect unused preload associations" do
492
+ Firm.includes(:clients).map(&:name)
493
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
494
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Firm, :clients)
495
+
496
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
497
+ end
498
+ end
499
+ end
500
+
501
+ describe Bullet::Detector::Association, "has_one" do
502
+ context "company => address" do
503
+ it "should detect non preload association" do
504
+ Company.all.each do |company|
505
+ company.address.name
506
+ end
507
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
508
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
509
+
510
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Company, :address)
511
+ end
512
+
513
+ it "should detect preload association" do
514
+ Company.includes(:address).each do |company|
515
+ company.address.name
516
+ end
517
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
518
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
519
+
520
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
521
+ end
522
+
523
+ it "should not detect preload association" do
524
+ Company.all.map(&:name)
525
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
526
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
527
+
528
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
529
+ end
530
+
531
+ it "should detect unused preload association" do
532
+ Company.includes(:address).map(&:name)
533
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
534
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Company, :address)
535
+
536
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
537
+ end
538
+ end
539
+ end
540
+
541
+ describe Bullet::Detector::Association, "has_one => has_many" do
542
+ it "should not detect preload association" do
543
+ user = User.first
544
+ user.submission.replies.map(&:name)
545
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
546
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
547
+
548
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
549
+ end
550
+ end
551
+
552
+ describe Bullet::Detector::Association, "call one association that in possible objects" do
553
+ it "should not detect preload association" do
554
+ Post.all
555
+ Post.first.comments.map(&:name)
556
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
557
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
558
+
559
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
560
+ end
561
+ end
562
+
563
+ describe Bullet::Detector::Association, "query immediately after creation" do
564
+ context "document => children" do
565
+ it 'should not detect non preload associations' do
566
+ document1 = Document.new
567
+ document1.children.build
568
+ document1.save
569
+
570
+ document2 = Document.new(parent: document1)
571
+ document2.save
572
+ document2.parent
573
+
574
+ document1.children.each.first
575
+
576
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
577
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
578
+
579
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
580
+ end
581
+ end
582
+ end
583
+
584
+ describe Bullet::Detector::Association, "STI" do
585
+ context "page => author" do
586
+ it "should detect non preload associations" do
587
+ Page.all.each do |page|
588
+ page.author.name
589
+ end
590
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
591
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
592
+
593
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Page, :author)
594
+ end
595
+
596
+ it "should detect preload associations" do
597
+ Page.includes(:author).each do |page|
598
+ page.author.name
599
+ end
600
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
601
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
602
+
603
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
604
+ end
605
+
606
+ it "should detect unused preload associations" do
607
+ Page.includes(:author).map(&:name)
608
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
609
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Page, :author)
610
+
611
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
612
+ end
613
+
614
+ it "should not detect preload associations" do
615
+ Page.all.map(&:name)
616
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
617
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
618
+
619
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
620
+ end
621
+ end
622
+
623
+ context "disable n plus one query" do
624
+ before { Bullet.n_plus_one_query_enable = false }
625
+ after { Bullet.n_plus_one_query_enable = true }
626
+
627
+ it "should not detect n plus one query" do
628
+ Post.all.each do |post|
629
+ post.comments.map(&:name)
630
+ end
631
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
632
+
633
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
634
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
635
+ end
636
+
637
+ it "should still detect unused eager loading" do
638
+ Post.includes(:comments).map(&:name)
639
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
640
+
641
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
642
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
643
+ end
644
+ end
645
+
646
+ context "disable unused eager loading" do
647
+ before { Bullet.unused_eager_loading_enable = false }
648
+ after { Bullet.unused_eager_loading_enable = true }
649
+
650
+ it "should not detect unused eager loading" do
651
+ Post.includes(:comments).map(&:name)
652
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
653
+
654
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
655
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
656
+ end
657
+
658
+ it "should still detect n plus one query" do
659
+ Post.all.each do |post|
660
+ post.comments.map(&:name)
661
+ end
662
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
663
+
664
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
665
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
666
+ end
667
+ end
668
+
669
+ context "whitelist n plus one query" do
670
+ before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
671
+ after { Bullet.clear_whitelist }
672
+
673
+ it "should not detect n plus one query" do
674
+ Post.all.each do |post|
675
+ post.comments.map(&:name)
676
+ end
677
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
678
+
679
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
680
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
681
+ end
682
+
683
+ it "should still detect unused eager loading" do
684
+ Post.includes(:comments).map(&:name)
685
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
686
+
687
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
688
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
689
+ end
690
+ end
691
+
692
+ context "whitelist unused eager loading" do
693
+ before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
694
+ after { Bullet.clear_whitelist }
695
+
696
+ it "should not detect unused eager loading" do
697
+ Post.includes(:comments).map(&:name)
698
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
699
+
700
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
701
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
702
+ end
703
+
704
+ it "should still detect n plus one query" do
705
+ Post.all.each do |post|
706
+ post.comments.map(&:name)
707
+ end
708
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
709
+
710
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
711
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
712
+ end
713
+ end
714
+ end
715
+ end