bullet 4.0.0 → 4.13.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.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +1 -1
  4. data/.travis.yml +17 -6
  5. data/CHANGELOG.md +86 -0
  6. data/Gemfile +13 -12
  7. data/Gemfile.mongoid +14 -0
  8. data/Gemfile.mongoid-2.4 +19 -0
  9. data/Gemfile.mongoid-2.5 +19 -0
  10. data/Gemfile.mongoid-2.6 +19 -0
  11. data/Gemfile.mongoid-2.7 +19 -0
  12. data/Gemfile.mongoid-2.8 +19 -0
  13. data/Gemfile.mongoid-3.0 +19 -0
  14. data/Gemfile.mongoid-3.1 +19 -0
  15. data/Gemfile.mongoid-4.0 +19 -0
  16. data/Gemfile.rails-3.0 +19 -0
  17. data/Gemfile.rails-3.1 +19 -0
  18. data/Gemfile.rails-3.2 +19 -0
  19. data/Gemfile.rails-4.0 +19 -0
  20. data/Gemfile.rails-4.1 +19 -0
  21. data/{Hacking.textile → Hacking.md} +10 -5
  22. data/README.md +432 -0
  23. data/Rakefile +13 -6
  24. data/bullet.gemspec +6 -3
  25. data/lib/bullet/active_record3.rb +49 -11
  26. data/lib/bullet/active_record3x.rb +134 -0
  27. data/lib/bullet/{active_record31.rb → active_record4.rb} +45 -15
  28. data/lib/bullet/active_record41.rb +128 -0
  29. data/lib/bullet/dependency.rb +81 -0
  30. data/lib/bullet/detector/association.rb +24 -68
  31. data/lib/bullet/detector/base.rb +0 -6
  32. data/lib/bullet/detector/counter_cache.rb +59 -0
  33. data/lib/bullet/detector/n_plus_one_query.rb +56 -15
  34. data/lib/bullet/detector/unused_eager_loading.rb +84 -0
  35. data/lib/bullet/detector.rb +2 -2
  36. data/lib/bullet/ext/object.rb +10 -2
  37. data/lib/bullet/{mongoid.rb → mongoid2x.rb} +18 -18
  38. data/lib/bullet/mongoid3x.rb +56 -0
  39. data/lib/bullet/mongoid4x.rb +56 -0
  40. data/lib/bullet/notification/base.rb +22 -4
  41. data/lib/bullet/notification/n_plus_one_query.rb +1 -1
  42. data/lib/bullet/notification.rb +2 -0
  43. data/lib/bullet/rack.rb +51 -17
  44. data/lib/bullet/registry/base.rb +1 -1
  45. data/lib/bullet/registry/object.rb +4 -4
  46. data/lib/bullet/version.rb +1 -2
  47. data/lib/bullet.rb +119 -39
  48. data/perf/benchmark.rb +1 -4
  49. data/spec/bullet/detector/association_spec.rb +2 -70
  50. data/spec/bullet/detector/base_spec.rb +0 -6
  51. data/spec/bullet/detector/counter_cache_spec.rb +56 -0
  52. data/spec/bullet/detector/n_plus_one_query_spec.rb +78 -34
  53. data/spec/bullet/detector/unused_eager_loading_spec.rb +88 -0
  54. data/spec/bullet/ext/object_spec.rb +18 -7
  55. data/spec/bullet/ext/string_spec.rb +2 -2
  56. data/spec/bullet/notification/base_spec.rb +68 -15
  57. data/spec/bullet/notification/counter_cache_spec.rb +2 -2
  58. data/spec/bullet/notification/n_plus_one_query_spec.rb +4 -3
  59. data/spec/bullet/notification/unused_eager_loading_spec.rb +2 -2
  60. data/spec/bullet/notification_collector_spec.rb +4 -4
  61. data/spec/bullet/rack_spec.rb +40 -39
  62. data/spec/bullet/registry/association_spec.rb +3 -3
  63. data/spec/bullet/registry/base_spec.rb +6 -6
  64. data/spec/bullet/registry/object_spec.rb +4 -5
  65. data/spec/bullet_spec.rb +41 -0
  66. data/spec/integration/active_record3/association_spec.rb +662 -0
  67. data/spec/integration/active_record4/association_spec.rb +660 -0
  68. data/spec/integration/counter_cache_spec.rb +63 -0
  69. data/spec/integration/mongoid/association_spec.rb +190 -208
  70. data/spec/models/category.rb +1 -1
  71. data/spec/models/client.rb +1 -1
  72. data/spec/models/comment.rb +2 -2
  73. data/spec/models/document.rb +2 -2
  74. data/spec/models/firm.rb +1 -1
  75. data/spec/models/mongoid/address.rb +2 -0
  76. data/spec/models/mongoid/category.rb +2 -0
  77. data/spec/models/mongoid/comment.rb +2 -0
  78. data/spec/models/mongoid/company.rb +2 -0
  79. data/spec/models/mongoid/entry.rb +2 -0
  80. data/spec/models/mongoid/post.rb +4 -0
  81. data/spec/models/mongoid/user.rb +5 -0
  82. data/spec/models/newspaper.rb +1 -1
  83. data/spec/models/pet.rb +1 -1
  84. data/spec/models/post.rb +6 -13
  85. data/spec/spec_helper.rb +60 -25
  86. data/spec/support/bullet_ext.rb +1 -1
  87. data/spec/support/mongo_seed.rb +26 -2
  88. data/spec/support/sqlite_seed.rb +0 -6
  89. data/test.sh +15 -0
  90. metadata +77 -54
  91. data/.rvmrc +0 -2
  92. data/.rvmrc.example +0 -2
  93. data/Gemfile.lock +0 -132
  94. data/Gemfile.rails-2.3.14 +0 -16
  95. data/Gemfile.rails-2.3.14.lock +0 -65
  96. data/Gemfile.rails-3.0.12 +0 -17
  97. data/Gemfile.rails-3.0.12.lock +0 -116
  98. data/Gemfile.rails-3.1.4 +0 -18
  99. data/Gemfile.rails-3.1.4.lock +0 -134
  100. data/README.textile +0 -395
  101. data/README_for_rails2.textile +0 -400
  102. data/lib/bullet/action_controller2.rb +0 -49
  103. data/lib/bullet/active_record2.rb +0 -121
  104. data/lib/bullet/detector/counter.rb +0 -48
  105. data/lib/bullet/detector/unused_eager_association.rb +0 -42
  106. data/spec/bullet/detector/counter_spec.rb +0 -64
  107. data/spec/bullet/detector/unused_eager_association_spec.rb +0 -62
  108. data/spec/integration/association_spec.rb +0 -593
  109. data/spec/integration/counter_spec.rb +0 -39
  110. data/spec/integration/rails2/association_spec.rb +0 -593
  111. data/spec/integration/rails2/counter_spec.rb +0 -39
  112. data/test.result +0 -2293
@@ -0,0 +1,660 @@
1
+ require 'spec_helper'
2
+
3
+ if !mongoid? && active_record4?
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
+ end
223
+
224
+ context "category => posts => writer" do
225
+ it "should not detect unused preload associations" do
226
+ category = Category.includes({:posts => :writer}).order("id DESC").find_by_name('first')
227
+ category.posts.map do |post|
228
+ post.name
229
+ post.writer.name
230
+ end
231
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
232
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Category, :posts)
233
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :writer)
234
+ end
235
+ end
236
+
237
+ context "scope for_category_name" do
238
+ it "should detect preload with post => category" do
239
+ Post.in_category_name('first').references(:categories).each do |post|
240
+ post.category.name
241
+ end
242
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
243
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
244
+
245
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
246
+ end
247
+
248
+ it "should not be unused preload post => category" do
249
+ Post.in_category_name('first').references(:categories).map(&:name)
250
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
251
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
252
+
253
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
254
+ end
255
+ end
256
+
257
+ context "scope preload_comments" do
258
+ it "should detect preload post => comments with scope" do
259
+ Post.preload_comments.each do |post|
260
+ post.comments.map(&:name)
261
+ end
262
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
263
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
264
+
265
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
266
+ end
267
+
268
+ it "should detect unused preload with scope" do
269
+ Post.preload_comments.map(&:name)
270
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
271
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
272
+
273
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
274
+ end
275
+ end
276
+ end
277
+
278
+ describe Bullet::Detector::Association, 'belongs_to' do
279
+ context "comment => post" do
280
+ it "should detect non preload with comment => post" do
281
+ Comment.all.each do |comment|
282
+ comment.post.name
283
+ end
284
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
285
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
286
+
287
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
288
+ end
289
+
290
+ it "should detect preload with one comment => post" do
291
+ Comment.first.post.name
292
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
293
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
294
+
295
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
296
+ end
297
+
298
+ it "should dtect preload with comment => post" do
299
+ Comment.includes(:post).each do |comment|
300
+ comment.post.name
301
+ end
302
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
303
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
304
+
305
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
306
+ end
307
+
308
+ it "should not detect preload with comment => post" do
309
+ Comment.all.map(&:name)
310
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
311
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
312
+
313
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
314
+ end
315
+
316
+ it "should detect unused preload with comments => post" do
317
+ Comment.includes(:post).map(&:name)
318
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
319
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Comment, :post)
320
+
321
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
322
+ end
323
+ end
324
+
325
+ context "comment => post => category" do
326
+ it "should detect non preload association with comment => post" do
327
+ Comment.all.each do |comment|
328
+ comment.post.category.name
329
+ end
330
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
331
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
332
+
333
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
334
+ end
335
+
336
+ it "should detect non preload association with post => category" do
337
+ Comment.includes(:post).each do |comment|
338
+ comment.post.category.name
339
+ end
340
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
341
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
342
+
343
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :category)
344
+ end
345
+
346
+ it "should not detect unpreload association" do
347
+ Comment.includes(:post => :category).each do |comment|
348
+ comment.post.category.name
349
+ end
350
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
351
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
352
+
353
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
354
+ end
355
+ end
356
+
357
+ context "comment => author, post => writer" do
358
+ it "should detect non preloaded writer" do
359
+ Comment.includes([:author, :post]).where(["base_users.id = ?", BaseUser.first]).references(:base_users).each do |comment|
360
+ comment.post.writer.name
361
+ end
362
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
363
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
364
+
365
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :writer)
366
+ end
367
+
368
+ it "should detect unused preload with comment => author" do
369
+ Comment.includes([:author, {:post => :writer}]).where(["base_users.id = ?", BaseUser.first]).references(:base_users).each do |comment|
370
+ comment.post.writer.name
371
+ end
372
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
373
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
374
+
375
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
376
+ end
377
+
378
+ it "should detect non preloading with writer => newspaper" do
379
+ Comment.includes(:post => :writer).where("posts.name like '%first%'").references(:posts).each do |comment|
380
+ comment.post.writer.newspaper.name
381
+ end
382
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
383
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
384
+
385
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Writer, :newspaper)
386
+ end
387
+
388
+ it "should not raise a stack error from posts to category" do
389
+ expect {
390
+ Comment.includes({:post => :category}).each do |com|
391
+ com.post.category
392
+ end
393
+ }.not_to raise_error()
394
+ end
395
+ end
396
+ end
397
+
398
+ describe Bullet::Detector::Association, 'has_and_belongs_to_many' do
399
+ context "students <=> teachers" do
400
+ it "should detect non preload associations" do
401
+ Student.all.each do |student|
402
+ student.teachers.map(&:name)
403
+ end
404
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
405
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
406
+
407
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Student, :teachers)
408
+ end
409
+
410
+ it "should detect preload associations" do
411
+ Student.includes(:teachers).each do |student|
412
+ student.teachers.map(&:name)
413
+ end
414
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
415
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
416
+
417
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
418
+ end
419
+
420
+ it "should detect unused preload associations" do
421
+ Student.includes(:teachers).map(&:name)
422
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
423
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Student, :teachers)
424
+
425
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
426
+ end
427
+
428
+ it "should detect no unused preload associations" do
429
+ Student.all.map(&:name)
430
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
431
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
432
+
433
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
434
+ end
435
+ end
436
+ end
437
+
438
+ describe Bullet::Detector::Association, 'has_many :through' do
439
+ context "firm => clients" do
440
+ it "should detect non preload associations" do
441
+ Firm.all.each do |firm|
442
+ firm.clients.map(&:name)
443
+ end
444
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
445
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
446
+
447
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Firm, :clients)
448
+ end
449
+
450
+ it "should detect preload associations" do
451
+ Firm.includes(:clients).each do |firm|
452
+ firm.clients.map(&:name)
453
+ end
454
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
455
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
456
+
457
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
458
+ end
459
+
460
+ it "should not detect preload associations" do
461
+ Firm.all.map(&:name)
462
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
463
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
464
+
465
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
466
+ end
467
+
468
+ it "should detect unused preload associations" do
469
+ Firm.includes(:clients).map(&:name)
470
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
471
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Firm, :clients)
472
+
473
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
474
+ end
475
+ end
476
+ end
477
+
478
+ describe Bullet::Detector::Association, "has_one" do
479
+ context "company => address" do
480
+ it "should detect non preload association" do
481
+ Company.all.each do |company|
482
+ company.address.name
483
+ end
484
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
485
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
486
+
487
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Company, :address)
488
+ end
489
+
490
+ it "should detect preload association" do
491
+ Company.includes(:address).each do |company|
492
+ company.address.name
493
+ end
494
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
495
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
496
+
497
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
498
+ end
499
+
500
+ it "should not detect preload association" do
501
+ Company.all.map(&:name)
502
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
503
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
504
+
505
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
506
+ end
507
+
508
+ it "should detect unused preload association" do
509
+ Company.includes(:address).map(&:name)
510
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
511
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Company, :address)
512
+
513
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
514
+ end
515
+ end
516
+ end
517
+
518
+ describe Bullet::Detector::Association, "call one association that in possible objects" do
519
+ it "should not detect preload association" do
520
+ Post.all
521
+ Post.first.comments.map(&:name)
522
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
523
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
524
+
525
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
526
+ end
527
+ end
528
+
529
+ describe Bullet::Detector::Association, "STI" do
530
+ context "page => author" do
531
+ it "should detect non preload associations" do
532
+ Page.all.each do |page|
533
+ page.author.name
534
+ end
535
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
536
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
537
+
538
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Page, :author)
539
+ end
540
+
541
+ it "should detect preload associations" do
542
+ Page.includes(:author).each do |page|
543
+ page.author.name
544
+ end
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
+
551
+ it "should detect unused preload associations" do
552
+ Page.includes(:author).map(&:name)
553
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
554
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Page, :author)
555
+
556
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
557
+ end
558
+
559
+ it "should not detect preload associations" do
560
+ Page.all.map(&:name)
561
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
562
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
563
+
564
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
565
+ end
566
+ end
567
+
568
+ context "disable n plus one query" do
569
+ before { Bullet.n_plus_one_query_enable = false }
570
+ after { Bullet.n_plus_one_query_enable = true }
571
+
572
+ it "should not detect n plus one query" do
573
+ Post.all.each do |post|
574
+ post.comments.map(&:name)
575
+ end
576
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
577
+
578
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
579
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
580
+ end
581
+
582
+ it "should still detect unused eager loading" do
583
+ Post.includes(:comments).map(&:name)
584
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
585
+
586
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
587
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
588
+ end
589
+ end
590
+
591
+ context "disable unused eager loading" do
592
+ before { Bullet.unused_eager_loading_enable = false }
593
+ after { Bullet.unused_eager_loading_enable = true }
594
+
595
+ it "should not detect unused eager loading" do
596
+ Post.includes(:comments).map(&:name)
597
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
598
+
599
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
600
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
601
+ end
602
+
603
+ it "should still detect n plus one query" do
604
+ Post.all.each do |post|
605
+ post.comments.map(&:name)
606
+ end
607
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
608
+
609
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
610
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
611
+ end
612
+ end
613
+
614
+ context "whitelist n plus one query" do
615
+ before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
616
+ after { Bullet.reset_whitelist }
617
+
618
+ it "should not detect n plus one query" do
619
+ Post.all.each do |post|
620
+ post.comments.map(&:name)
621
+ end
622
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
623
+
624
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
625
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
626
+ end
627
+
628
+ it "should still detect unused eager loading" do
629
+ Post.includes(:comments).map(&:name)
630
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
631
+
632
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
633
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
634
+ end
635
+ end
636
+
637
+ context "whitelist unused eager loading" do
638
+ before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
639
+ after { Bullet.reset_whitelist }
640
+
641
+ it "should not detect unused eager loading" do
642
+ Post.includes(:comments).map(&:name)
643
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
644
+
645
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
646
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
647
+ end
648
+
649
+ it "should still detect n plus one query" do
650
+ Post.all.each do |post|
651
+ post.comments.map(&:name)
652
+ end
653
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
654
+
655
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
656
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
657
+ end
658
+ end
659
+ end
660
+ end