bullet_instructure 4.0.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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +20 -0
  6. data/CHANGELOG.md +75 -0
  7. data/Gemfile +19 -0
  8. data/Gemfile.mongoid +14 -0
  9. data/Gemfile.mongoid-2.4 +19 -0
  10. data/Gemfile.mongoid-2.5 +19 -0
  11. data/Gemfile.mongoid-2.6 +19 -0
  12. data/Gemfile.mongoid-2.7 +19 -0
  13. data/Gemfile.mongoid-2.8 +19 -0
  14. data/Gemfile.mongoid-3.0 +19 -0
  15. data/Gemfile.mongoid-3.1 +19 -0
  16. data/Gemfile.mongoid-4.0 +19 -0
  17. data/Gemfile.rails-3.0 +19 -0
  18. data/Gemfile.rails-3.1 +19 -0
  19. data/Gemfile.rails-3.2 +19 -0
  20. data/Gemfile.rails-4.0 +19 -0
  21. data/Gemfile.rails-4.1 +19 -0
  22. data/Guardfile +8 -0
  23. data/Hacking.md +74 -0
  24. data/MIT-LICENSE +20 -0
  25. data/README.md +428 -0
  26. data/Rakefile +52 -0
  27. data/bullet_instructure.gemspec +27 -0
  28. data/lib/bullet.rb +196 -0
  29. data/lib/bullet/active_record3.rb +148 -0
  30. data/lib/bullet/active_record3x.rb +128 -0
  31. data/lib/bullet/active_record4.rb +128 -0
  32. data/lib/bullet/active_record41.rb +121 -0
  33. data/lib/bullet/dependency.rb +81 -0
  34. data/lib/bullet/detector.rb +9 -0
  35. data/lib/bullet/detector/association.rb +67 -0
  36. data/lib/bullet/detector/base.rb +6 -0
  37. data/lib/bullet/detector/counter_cache.rb +59 -0
  38. data/lib/bullet/detector/n_plus_one_query.rb +89 -0
  39. data/lib/bullet/detector/unused_eager_loading.rb +84 -0
  40. data/lib/bullet/ext/object.rb +9 -0
  41. data/lib/bullet/ext/string.rb +5 -0
  42. data/lib/bullet/mongoid2x.rb +56 -0
  43. data/lib/bullet/mongoid3x.rb +56 -0
  44. data/lib/bullet/mongoid4x.rb +56 -0
  45. data/lib/bullet/notification.rb +10 -0
  46. data/lib/bullet/notification/base.rb +97 -0
  47. data/lib/bullet/notification/counter_cache.rb +13 -0
  48. data/lib/bullet/notification/n_plus_one_query.rb +28 -0
  49. data/lib/bullet/notification/unused_eager_loading.rb +13 -0
  50. data/lib/bullet/notification_collector.rb +24 -0
  51. data/lib/bullet/rack.rb +81 -0
  52. data/lib/bullet/registry.rb +7 -0
  53. data/lib/bullet/registry/association.rb +13 -0
  54. data/lib/bullet/registry/base.rb +40 -0
  55. data/lib/bullet/registry/object.rb +13 -0
  56. data/lib/bullet/version.rb +4 -0
  57. data/perf/benchmark.rb +121 -0
  58. data/rails/init.rb +1 -0
  59. data/spec/bullet/detector/association_spec.rb +26 -0
  60. data/spec/bullet/detector/base_spec.rb +8 -0
  61. data/spec/bullet/detector/counter_cache_spec.rb +56 -0
  62. data/spec/bullet/detector/n_plus_one_query_spec.rb +138 -0
  63. data/spec/bullet/detector/unused_eager_loading_spec.rb +88 -0
  64. data/spec/bullet/ext/object_spec.rb +17 -0
  65. data/spec/bullet/ext/string_spec.rb +13 -0
  66. data/spec/bullet/notification/base_spec.rb +83 -0
  67. data/spec/bullet/notification/counter_cache_spec.rb +12 -0
  68. data/spec/bullet/notification/n_plus_one_query_spec.rb +14 -0
  69. data/spec/bullet/notification/unused_eager_loading_spec.rb +12 -0
  70. data/spec/bullet/notification_collector_spec.rb +32 -0
  71. data/spec/bullet/rack_spec.rb +97 -0
  72. data/spec/bullet/registry/association_spec.rb +26 -0
  73. data/spec/bullet/registry/base_spec.rb +44 -0
  74. data/spec/bullet/registry/object_spec.rb +24 -0
  75. data/spec/bullet_spec.rb +41 -0
  76. data/spec/integration/active_record3/association_spec.rb +651 -0
  77. data/spec/integration/active_record4/association_spec.rb +649 -0
  78. data/spec/integration/counter_cache_spec.rb +63 -0
  79. data/spec/integration/mongoid/association_spec.rb +258 -0
  80. data/spec/models/address.rb +3 -0
  81. data/spec/models/author.rb +3 -0
  82. data/spec/models/base_user.rb +5 -0
  83. data/spec/models/category.rb +7 -0
  84. data/spec/models/city.rb +3 -0
  85. data/spec/models/client.rb +4 -0
  86. data/spec/models/comment.rb +4 -0
  87. data/spec/models/company.rb +3 -0
  88. data/spec/models/country.rb +3 -0
  89. data/spec/models/document.rb +5 -0
  90. data/spec/models/entry.rb +3 -0
  91. data/spec/models/firm.rb +4 -0
  92. data/spec/models/folder.rb +2 -0
  93. data/spec/models/mongoid/address.rb +7 -0
  94. data/spec/models/mongoid/category.rb +8 -0
  95. data/spec/models/mongoid/comment.rb +7 -0
  96. data/spec/models/mongoid/company.rb +7 -0
  97. data/spec/models/mongoid/entry.rb +7 -0
  98. data/spec/models/mongoid/post.rb +12 -0
  99. data/spec/models/mongoid/user.rb +5 -0
  100. data/spec/models/newspaper.rb +3 -0
  101. data/spec/models/page.rb +2 -0
  102. data/spec/models/person.rb +3 -0
  103. data/spec/models/pet.rb +3 -0
  104. data/spec/models/post.rb +10 -0
  105. data/spec/models/relationship.rb +4 -0
  106. data/spec/models/student.rb +3 -0
  107. data/spec/models/submission.rb +4 -0
  108. data/spec/models/teacher.rb +3 -0
  109. data/spec/models/user.rb +4 -0
  110. data/spec/models/writer.rb +2 -0
  111. data/spec/spec_helper.rb +103 -0
  112. data/spec/support/bullet_ext.rb +55 -0
  113. data/spec/support/mongo_seed.rb +65 -0
  114. data/spec/support/rack_double.rb +55 -0
  115. data/spec/support/sqlite_seed.rb +229 -0
  116. data/tasks/bullet_tasks.rake +9 -0
  117. data/test.sh +15 -0
  118. metadata +246 -0
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ module Bullet
4
+ module Registry
5
+ describe Association do
6
+ subject { Association.new.tap { |association| association.add(["key1", "key2"], "value") } }
7
+
8
+ context "#merge" do
9
+ it "should merge key/value" do
10
+ subject.merge("key0", "value0")
11
+ expect(subject["key0"]).to be_include("value0")
12
+ end
13
+ end
14
+
15
+ context "#similarly_associated" do
16
+ it "should return similarly associated keys" do
17
+ expect(subject.similarly_associated("key1", Set.new(["value"]))).to eq(["key1", "key2"])
18
+ end
19
+
20
+ it "should return empty if key does not exist" do
21
+ expect(subject.similarly_associated("key3", Set.new(["value"]))).to be_empty
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ module Bullet
4
+ module Registry
5
+ describe Base do
6
+ subject { Base.new.tap { |base| base.add("key", "value") } }
7
+
8
+ context "#[]" do
9
+ it "should get value by key" do
10
+ expect(subject["key"]).to eq(Set.new(["value"]))
11
+ end
12
+ end
13
+
14
+ context "#delete" do
15
+ it "should delete key" do
16
+ subject.delete("key")
17
+ expect(subject["key"]).to be_nil
18
+ end
19
+ end
20
+
21
+ context "#add" do
22
+ it "should add value with string" do
23
+ subject.add("key", "new_value")
24
+ expect(subject["key"]).to eq(Set.new(["value", "new_value"]))
25
+ end
26
+
27
+ it "should add value with array" do
28
+ subject.add("key", ["value1", "value2"])
29
+ expect(subject["key"]).to eq(Set.new(["value", "value1", "value2"]))
30
+ end
31
+ end
32
+
33
+ context "#include?" do
34
+ it "should include key/value" do
35
+ expect(subject.include?("key", "value")).to eq true
36
+ end
37
+
38
+ it "should not include wrong key/value" do
39
+ expect(subject.include?("key", "val")).to eq false
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ module Bullet
4
+ module Registry
5
+ describe Object do
6
+ let(:post) { Post.first }
7
+ let(:another_post) { Post.last }
8
+ subject { Object.new.tap { |object| object.add(post.bullet_key) } }
9
+
10
+ context "#include?" do
11
+ it "should include the object" do
12
+ expect(subject).to be_include(post.bullet_key)
13
+ end
14
+ end
15
+
16
+ context "#add" do
17
+ it "should add an object" do
18
+ subject.add(another_post.bullet_key)
19
+ expect(subject).to be_include(another_post.bullet_key)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Bullet, focused: true do
4
+ subject { Bullet }
5
+
6
+ describe '#enable' do
7
+
8
+ context 'enable Bullet' do
9
+ before do
10
+ # Bullet.enable
11
+ # Do nothing. Bullet has already been enabled for the whole test suite.
12
+ end
13
+
14
+ it 'should be enabled' do
15
+ expect(subject).to be_enable
16
+ end
17
+
18
+ context 'disable Bullet' do
19
+ before do
20
+ Bullet.enable = false
21
+ end
22
+
23
+ it 'should be disabled' do
24
+ expect(subject).to_not be_enable
25
+ end
26
+
27
+ context 'enable Bullet again without patching again the orms' do
28
+ before do
29
+ Bullet::Mongoid.should_not_receive(:enable) if defined? Bullet::Mongoid
30
+ Bullet::ActiveRecord.should_not_receive(:enable) if defined? Bullet::ActiveRecord
31
+ Bullet.enable = true
32
+ end
33
+
34
+ it 'should be enabled again' do
35
+ expect(subject).to be_enable
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,651 @@
1
+ require 'spec_helper'
2
+
3
+ if !mongoid? && active_record3?
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
+ end
65
+
66
+ context "category => posts => comments" do
67
+ it "should detect non preload category => posts => comments" do
68
+ Category.all.each do |category|
69
+ category.posts.each do |post|
70
+ post.comments.map(&:name)
71
+ end
72
+ end
73
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
74
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
75
+
76
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :posts)
77
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
78
+ end
79
+
80
+ it "should detect preload category => posts, but no post => comments" do
81
+ Category.includes(:posts).each do |category|
82
+ category.posts.each do |post|
83
+ post.comments.map(&:name)
84
+ end
85
+ end
86
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
87
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
88
+
89
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Category, :posts)
90
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
91
+ end
92
+
93
+ it "should detect preload with category => posts => comments" do
94
+ Category.includes({:posts => :comments}).each do |category|
95
+ category.posts.each do |post|
96
+ post.comments.map(&:name)
97
+ end
98
+ end
99
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
100
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
101
+
102
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
103
+ end
104
+
105
+ it "should detect preload with category => posts => comments with posts.id > 0" do
106
+ Category.includes({:posts => :comments}).where('posts.id > 0').each do |category|
107
+ category.posts.each do |post|
108
+ post.comments.map(&:name)
109
+ end
110
+ end
111
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
112
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
113
+
114
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
115
+ end
116
+
117
+ it "should detect unused preload with category => posts => comments" do
118
+ Category.includes({:posts => :comments}).map(&:name)
119
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
120
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
121
+
122
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
123
+ end
124
+
125
+ it "should detect unused preload with post => commnets, no category => posts" do
126
+ Category.includes({:posts => :comments}).each do |category|
127
+ category.posts.map(&:name)
128
+ end
129
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
130
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
131
+
132
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
133
+ end
134
+ end
135
+
136
+ context "category => posts, category => entries" do
137
+ it "should detect non preload with category => [posts, entries]" do
138
+ Category.all.each do |category|
139
+ category.posts.map(&:name)
140
+ category.entries.map(&:name)
141
+ end
142
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
143
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
144
+
145
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :posts)
146
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :entries)
147
+ end
148
+
149
+ it "should detect preload with category => posts, but not with category => entries" do
150
+ Category.includes(:posts).each do |category|
151
+ category.posts.map(&:name)
152
+ category.entries.map(&:name)
153
+ end
154
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
155
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
156
+
157
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Category, :posts)
158
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :entries)
159
+ end
160
+
161
+ it "should detect preload with category => [posts, entries]" do
162
+ Category.includes([:posts, :entries]).each do |category|
163
+ category.posts.map(&:name)
164
+ category.entries.map(&:name)
165
+ end
166
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
167
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
168
+
169
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
170
+ end
171
+
172
+ it "should detect unused preload with category => [posts, entries]" do
173
+ Category.includes([:posts, :entries]).map(&:name)
174
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
175
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :posts)
176
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :entries)
177
+
178
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
179
+ end
180
+
181
+ it "should detect unused preload with category => entries, but not with category => posts" do
182
+ Category.includes([:posts, :entries]).each do |category|
183
+ category.posts.map(&:name)
184
+ end
185
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
186
+ expect(Bullet::Detector::Association).not_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
+ end
192
+
193
+ context "post => comment" do
194
+ it "should detect unused preload with post => comments" do
195
+ Post.includes(:comments).each do |post|
196
+ post.comments.first.name
197
+ end
198
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
199
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :comments)
200
+
201
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
202
+ end
203
+
204
+ it "should detect preload with post => commnets" do
205
+ Post.first.comments.map(&:name)
206
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
207
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
208
+
209
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
210
+ end
211
+ end
212
+
213
+ context "category => posts => writer" do
214
+ it "should not detect unused preload associations" do
215
+ category = Category.includes({:posts => :writer}).order("id DESC").find_by_name('first')
216
+ category.posts.map do |post|
217
+ post.name
218
+ post.writer.name
219
+ end
220
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
221
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Category, :posts)
222
+ expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :writer)
223
+
224
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
225
+ end
226
+ end
227
+
228
+ context "scope for_category_name" do
229
+ it "should detect preload with post => category" do
230
+ Post.in_category_name('first').each do |post|
231
+ post.category.name
232
+ end
233
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
234
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
235
+
236
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
237
+ end
238
+
239
+ it "should not be unused preload post => category" do
240
+ Post.in_category_name('first').all.map(&:name)
241
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
242
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
243
+
244
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
245
+ end
246
+ end
247
+
248
+ context "scope preload_comments" do
249
+ it "should detect preload post => comments with scope" do
250
+ Post.preload_comments.each do |post|
251
+ post.comments.map(&:name)
252
+ end
253
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
254
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
255
+
256
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
257
+ end
258
+
259
+ it "should detect unused preload with scope" do
260
+ Post.preload_comments.map(&:name)
261
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
262
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
263
+
264
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
265
+ end
266
+ end
267
+ end
268
+
269
+ describe Bullet::Detector::Association, 'belongs_to' do
270
+ context "comment => post" do
271
+ it "should detect non preload with comment => post" do
272
+ Comment.all.each do |comment|
273
+ comment.post.name
274
+ end
275
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
276
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
277
+
278
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
279
+ end
280
+
281
+ it "should detect preload with one comment => post" do
282
+ Comment.first.post.name
283
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
284
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
285
+
286
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
287
+ end
288
+
289
+ it "should dtect preload with comment => post" do
290
+ Comment.includes(:post).each do |comment|
291
+ comment.post.name
292
+ end
293
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
294
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
295
+
296
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
297
+ end
298
+
299
+ it "should not detect preload with comment => post" do
300
+ Comment.all.map(&:name)
301
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
302
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
303
+
304
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
305
+ end
306
+
307
+ it "should detect unused preload with comments => post" do
308
+ Comment.includes(:post).map(&:name)
309
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
310
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Comment, :post)
311
+
312
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
313
+ end
314
+ end
315
+
316
+ context "comment => post => category" do
317
+ it "should detect non preload association with comment => post" do
318
+ Comment.all.each do |comment|
319
+ comment.post.category.name
320
+ end
321
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
322
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
323
+
324
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
325
+ end
326
+
327
+ it "should detect non preload association with post => category" do
328
+ Comment.includes(:post).each do |comment|
329
+ comment.post.category.name
330
+ end
331
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
332
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
333
+
334
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :category)
335
+ end
336
+
337
+ it "should not detect unpreload association" do
338
+ Comment.includes(:post => :category).each do |comment|
339
+ comment.post.category.name
340
+ end
341
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
342
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
343
+
344
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
345
+ end
346
+ end
347
+
348
+ context "comment => author, post => writer" do
349
+ it "should detect non preloaded writer" do
350
+ Comment.includes([:author, :post]).where(["base_users.id = ?", BaseUser.first]).each do |comment|
351
+ comment.post.writer.name
352
+ end
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_detecting_unpreloaded_association_for(Post, :writer)
357
+ end
358
+
359
+ it "should detect unused preload with comment => author" do
360
+ Comment.includes([:author, {:post => :writer}]).where(["base_users.id = ?", BaseUser.first]).each do |comment|
361
+ comment.post.writer.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_completely_preloading_associations
367
+ end
368
+
369
+ it "should detect non preloading with writer => newspaper" do
370
+ Comment.all(:include => {:post => :writer}, :conditions => "posts.name like '%first%'").each do |comment|
371
+ comment.post.writer.newspaper.name
372
+ end
373
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
374
+ Bullet::Detector::Association.should_not be_has_unused_preload_associations
375
+
376
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Writer, :newspaper)
377
+ end
378
+
379
+ it "should not raise a stack error from posts to category" do
380
+ expect {
381
+ Comment.includes({:post => :category}).each do |com|
382
+ com.post.category
383
+ end
384
+ }.not_to raise_error
385
+ end
386
+ end
387
+ end
388
+
389
+ describe Bullet::Detector::Association, 'has_and_belongs_to_many' do
390
+ context "students <=> teachers" do
391
+ it "should detect non preload associations" do
392
+ Student.all.each do |student|
393
+ student.teachers.map(&: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_detecting_unpreloaded_association_for(Student, :teachers)
399
+ end
400
+
401
+ it "should detect preload associations" do
402
+ Student.includes(:teachers).each do |student|
403
+ student.teachers.map(&: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_completely_preloading_associations
409
+ end
410
+
411
+ it "should detect unused preload associations" do
412
+ Student.includes(:teachers).map(&:name)
413
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
414
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Student, :teachers)
415
+
416
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
417
+ end
418
+
419
+ it "should detect no unused preload associations" do
420
+ Student.all.map(&:name)
421
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
422
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
423
+
424
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
425
+ end
426
+ end
427
+ end
428
+
429
+ describe Bullet::Detector::Association, 'has_many :through' do
430
+ context "firm => clients" do
431
+ it "should detect non preload associations" do
432
+ Firm.all.each do |firm|
433
+ firm.clients.map(&:name)
434
+ end
435
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
436
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
437
+
438
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Firm, :clients)
439
+ end
440
+
441
+ it "should detect preload associations" do
442
+ Firm.includes(:clients).each do |firm|
443
+ firm.clients.map(&:name)
444
+ end
445
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
446
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
447
+
448
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
449
+ end
450
+
451
+ it "should not detect preload associations" do
452
+ Firm.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
+
459
+ it "should detect unused preload associations" do
460
+ Firm.includes(:clients).map(&:name)
461
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
462
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Firm, :clients)
463
+
464
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
465
+ end
466
+ end
467
+ end
468
+
469
+ describe Bullet::Detector::Association, "has_one" do
470
+ context "company => address" do
471
+ it "should detect non preload association" do
472
+ Company.all.each do |company|
473
+ company.address.name
474
+ end
475
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
476
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
477
+
478
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Company, :address)
479
+ end
480
+
481
+ it "should detect preload association" do
482
+ Company.includes(:address).each do |company|
483
+ company.address.name
484
+ end
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 not detect preload association" do
492
+ Company.all.map(&:name)
493
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
494
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
495
+
496
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
497
+ end
498
+
499
+ it "should detect unused preload association" do
500
+ Company.includes(:address).map(&:name)
501
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
502
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Company, :address)
503
+
504
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
505
+ end
506
+ end
507
+ end
508
+
509
+ describe Bullet::Detector::Association, "call one association that in possible objects" do
510
+ it "should not detect preload association" do
511
+ Post.all
512
+ Post.first.comments.map(&:name)
513
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
514
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
515
+
516
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
517
+ end
518
+ end
519
+
520
+ describe Bullet::Detector::Association, "STI" do
521
+ context "page => author" do
522
+ it "should detect non preload associations" do
523
+ Page.all.each do |page|
524
+ page.author.name
525
+ end
526
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
527
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
528
+
529
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Page, :author)
530
+ end
531
+
532
+ it "should detect preload associations" do
533
+ Page.includes(:author).each do |page|
534
+ page.author.name
535
+ end
536
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
537
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
538
+
539
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
540
+ end
541
+
542
+ it "should detect unused preload associations" do
543
+ Page.includes(:author).map(&:name)
544
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
545
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Page, :author)
546
+
547
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
548
+ end
549
+
550
+ it "should not detect preload associations" do
551
+ Page.all.map(&:name)
552
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
553
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
554
+
555
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
556
+ end
557
+ end
558
+
559
+ context "disable n plus one query" do
560
+ before { Bullet.n_plus_one_query_enable = false }
561
+ after { Bullet.n_plus_one_query_enable = true }
562
+
563
+ it "should not detect n plus one query" do
564
+ Post.all.each do |post|
565
+ post.comments.map(&:name)
566
+ end
567
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
568
+
569
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
570
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
571
+ end
572
+
573
+ it "should still detect unused eager loading" do
574
+ Post.includes(:comments).map(&:name)
575
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
576
+
577
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
578
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
579
+ end
580
+ end
581
+
582
+ context "disable unused eager loading" do
583
+ before { Bullet.unused_eager_loading_enable = false }
584
+ after { Bullet.unused_eager_loading_enable = true }
585
+
586
+ it "should not detect unused eager loading" do
587
+ Post.includes(:comments).map(&:name)
588
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
589
+
590
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
591
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
592
+ end
593
+
594
+ it "should still detect n plus one query" do
595
+ Post.all.each do |post|
596
+ post.comments.map(&:name)
597
+ end
598
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
599
+
600
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
601
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
602
+ end
603
+ end
604
+
605
+ context "whitelist n plus one query" do
606
+ before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
607
+ after { Bullet.reset_whitelist }
608
+
609
+ it "should not detect n plus one query" do
610
+ Post.all.each do |post|
611
+ post.comments.map(&:name)
612
+ end
613
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
614
+
615
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
616
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
617
+ end
618
+
619
+ it "should still detect unused eager loading" do
620
+ Post.includes(:comments).map(&:name)
621
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
622
+
623
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
624
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
625
+ end
626
+ end
627
+
628
+ context "whitelist unused eager loading" do
629
+ before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
630
+ after { Bullet.reset_whitelist }
631
+
632
+ it "should not detect unused eager loading" do
633
+ Post.includes(:comments).map(&:name)
634
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
635
+
636
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
637
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
638
+ end
639
+
640
+ it "should still detect n plus one query" do
641
+ Post.all.each do |post|
642
+ post.comments.map(&:name)
643
+ end
644
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
645
+
646
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
647
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
648
+ end
649
+ end
650
+ end
651
+ end