bullet 4.13.1 → 5.5.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -11
  4. data/CHANGELOG.md +62 -3
  5. data/Gemfile.mongoid +0 -2
  6. data/Gemfile.mongoid-4.0 +1 -5
  7. data/{Gemfile.mongoid-2.8 → Gemfile.mongoid-5.0} +2 -6
  8. data/{Gemfile.mongoid-2.5 → Gemfile.mongoid-6.0} +2 -6
  9. data/Gemfile.rails-4.0 +2 -5
  10. data/Gemfile.rails-4.1 +2 -5
  11. data/{Gemfile.rails-3.0 → Gemfile.rails-4.2} +3 -6
  12. data/{Gemfile.rails-3.1 → Gemfile.rails-5.0} +2 -6
  13. data/Hacking.md +1 -0
  14. data/README.md +39 -7
  15. data/bullet.gemspec +1 -1
  16. data/lib/bullet/active_record4.rb +109 -33
  17. data/lib/bullet/active_record41.rb +99 -37
  18. data/lib/bullet/active_record42.rb +251 -0
  19. data/lib/bullet/active_record5.rb +243 -0
  20. data/lib/bullet/dependency.rb +34 -28
  21. data/lib/bullet/detector/association.rb +16 -16
  22. data/lib/bullet/detector/counter_cache.rb +13 -13
  23. data/lib/bullet/detector/n_plus_one_query.rb +30 -35
  24. data/lib/bullet/detector/unused_eager_loading.rb +12 -11
  25. data/lib/bullet/ext/object.rb +4 -2
  26. data/lib/bullet/{mongoid3x.rb → mongoid5x.rb} +3 -3
  27. data/lib/bullet/{mongoid2x.rb → mongoid6x.rb} +12 -12
  28. data/lib/bullet/notification/base.rb +9 -13
  29. data/lib/bullet/notification/n_plus_one_query.rb +8 -6
  30. data/lib/bullet/notification/unused_eager_loading.rb +18 -1
  31. data/lib/bullet/rack.rb +28 -16
  32. data/lib/bullet/stack_trace_filter.rb +34 -0
  33. data/lib/bullet/version.rb +1 -1
  34. data/lib/bullet.rb +48 -14
  35. data/spec/bullet/detector/counter_cache_spec.rb +8 -8
  36. data/spec/bullet/detector/n_plus_one_query_spec.rb +46 -31
  37. data/spec/bullet/detector/unused_eager_loading_spec.rb +17 -3
  38. data/spec/bullet/ext/object_spec.rb +6 -0
  39. data/spec/bullet/notification/base_spec.rb +4 -29
  40. data/spec/bullet/notification/n_plus_one_query_spec.rb +4 -4
  41. data/spec/bullet/notification/unused_eager_loading_spec.rb +3 -3
  42. data/spec/bullet/rack_spec.rb +38 -7
  43. data/spec/bullet_spec.rb +93 -0
  44. data/spec/integration/active_record4/association_spec.rb +112 -4
  45. data/spec/integration/{active_record3 → active_record5}/association_spec.rb +121 -15
  46. data/spec/integration/counter_cache_spec.rb +24 -1
  47. data/spec/models/category.rb +4 -1
  48. data/spec/models/comment.rb +2 -0
  49. data/spec/models/post.rb +7 -2
  50. data/spec/models/reply.rb +3 -0
  51. data/spec/models/submission.rb +1 -1
  52. data/spec/spec_helper.rb +3 -5
  53. data/spec/support/mongo_seed.rb +13 -0
  54. data/spec/support/sqlite_seed.rb +15 -6
  55. data/test.sh +4 -10
  56. data/update.sh +7 -0
  57. metadata +21 -23
  58. data/Gemfile.mongoid-2.4 +0 -19
  59. data/Gemfile.mongoid-2.6 +0 -19
  60. data/Gemfile.mongoid-2.7 +0 -19
  61. data/Gemfile.mongoid-3.0 +0 -19
  62. data/Gemfile.mongoid-3.1 +0 -19
  63. data/Gemfile.rails-3.2 +0 -19
  64. data/lib/bullet/active_record3.rb +0 -154
  65. data/lib/bullet/active_record3x.rb +0 -134
@@ -5,7 +5,8 @@ module Bullet
5
5
  describe UnusedEagerLoading do
6
6
  before(:all) do
7
7
  @post = Post.first
8
- @post2 = Post.last
8
+ @post2 = Post.all[1]
9
+ @post3 = Post.last
9
10
  end
10
11
 
11
12
  context ".call_associations" do
@@ -38,9 +39,11 @@ module Bullet
38
39
  end
39
40
 
40
41
  context ".check_unused_preload_associations" do
42
+ let(:paths) { ["/dir1", "/dir1/subdir"] }
41
43
  it "should create notification if object_association_diff is not empty" do
42
44
  UnusedEagerLoading.add_object_associations(@post, :association)
43
- expect(UnusedEagerLoading).to receive(:create_notification).with("Post", [:association])
45
+ allow(UnusedEagerLoading).to receive(:caller_in_project).and_return(paths)
46
+ expect(UnusedEagerLoading).to receive(:create_notification).with(paths, "Post", [:association])
44
47
  UnusedEagerLoading.check_unused_preload_associations
45
48
  end
46
49
 
@@ -72,7 +75,18 @@ module Bullet
72
75
  UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
73
76
  expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
74
77
  expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
75
- expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :association2)
78
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association2)
79
+ end
80
+
81
+ it "should vmerge objects recursively, associations pair for existing eager_loadings" do
82
+ UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
83
+ UnusedEagerLoading.add_eager_loadings([@post, @post3], :association1)
84
+ UnusedEagerLoading.add_eager_loadings([@post, @post3], :association2)
85
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
86
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
87
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association1)
88
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post3.bullet_key], :association1)
89
+ expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post3.bullet_key], :association2)
76
90
  end
77
91
 
78
92
  it "should delete objects, associations pair for existing eager_loadings" do
@@ -27,5 +27,11 @@ describe Object do
27
27
  expect(post.primary_key_value).to eq(post.name)
28
28
  Post.primary_key = 'id'
29
29
  end
30
+
31
+ it "should return value for multiple primary keys" do
32
+ post = Post.first
33
+ allow(Post).to receive(:primary_keys).and_return([:category_id, :writer_id])
34
+ expect(post.primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
35
+ end
30
36
  end
31
37
  end
@@ -30,14 +30,14 @@ module Bullet
30
30
  end
31
31
 
32
32
  it "should return blank if no user available" do
33
- temp_env_variable("USER","") do
33
+ temp_env_variable("USER", "") do
34
34
  expect(subject).to receive(:`).with("whoami").and_return("")
35
35
  expect(subject.whoami).to eq("")
36
36
  end
37
37
  end
38
38
 
39
39
  it "should return blank if whoami is not available" do
40
- temp_env_variable("USER","") do
40
+ temp_env_variable("USER", "") do
41
41
  expect(subject).to receive(:`).with("whoami").and_raise(Errno::ENOENT)
42
42
  expect(subject.whoami).to eq("")
43
43
  end
@@ -56,33 +56,8 @@ module Bullet
56
56
  context "#body_with_caller" do
57
57
  it "should return body" do
58
58
  allow(subject).to receive(:body).and_return("body")
59
- expect(subject.body_with_caller).to eq("body")
60
- end
61
- end
62
-
63
- context "#standard_notice" do
64
- it "should return title + body" do
65
- allow(subject).to receive(:title).and_return("title")
66
- allow(subject).to receive(:body).and_return("body")
67
- expect(subject.standard_notice).to eq("title\nbody")
68
- end
69
- end
70
-
71
- context "#full_notice" do
72
- it "should return whoami + url + title + body_with_caller" do
73
- allow(subject).to receive(:whoami).and_return("whoami")
74
- allow(subject).to receive(:url).and_return("url")
75
- allow(subject).to receive(:title).and_return("title")
76
- allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
77
- expect(subject.full_notice).to eq("whoami\nurl\ntitle\nbody_with_caller")
78
- end
79
-
80
- it "should return url + title + body_with_caller" do
81
- allow(subject).to receive(:whoami).and_return("")
82
- allow(subject).to receive(:url).and_return("url")
83
- allow(subject).to receive(:title).and_return("title")
84
- allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
85
- expect(subject.full_notice).to eq("url\ntitle\nbody_with_caller")
59
+ allow(subject).to receive(:call_stack_messages).and_return("call_stack_messages")
60
+ expect(subject.body_with_caller).to eq("body\ncall_stack_messages\n")
86
61
  end
87
62
  end
88
63
 
@@ -5,10 +5,10 @@ module Bullet
5
5
  describe NPlusOneQuery do
6
6
  subject { NPlusOneQuery.new([["caller1", "caller2"]], Post, [:comments, :votes], "path") }
7
7
 
8
- it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2") }
9
- it { expect([ subject.body_with_caller, subject.body_with_caller]).to eq([ " Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2", " Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2" ]) }
10
- it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]") }
11
- it { expect(subject.title).to eq("N+1 Query in path") }
8
+ it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n") }
9
+ it { expect([subject.body_with_caller, subject.body_with_caller]).to eq([ " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n", " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n" ]) }
10
+ it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]") }
11
+ it { expect(subject.title).to eq("USE eager loading in path") }
12
12
  end
13
13
  end
14
14
  end
@@ -3,10 +3,10 @@ require 'spec_helper'
3
3
  module Bullet
4
4
  module Notification
5
5
  describe UnusedEagerLoading do
6
- subject { UnusedEagerLoading.new(Post, [:comments, :votes], "path") }
6
+ subject { UnusedEagerLoading.new([""], Post, [:comments, :votes], "path") }
7
7
 
8
- it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :include => [:comments, :votes]") }
9
- it { expect(subject.title).to eq("Unused Eager Loading in path") }
8
+ it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :includes => [:comments, :votes]") }
9
+ it { expect(subject.title).to eq("AVOID eager loading in path") }
10
10
  end
11
11
  end
12
12
  end
@@ -60,26 +60,26 @@ module Bullet
60
60
  it "should return original response body" do
61
61
  expected_response = Support::ResponseDouble.new "Actual body"
62
62
  app.response = expected_response
63
- _, _, response = middleware.call([])
63
+ _, _, response = middleware.call({})
64
64
  expect(response).to eq(expected_response)
65
65
  end
66
66
 
67
67
  it "should change response body if notification is active" do
68
- expect(Bullet).to receive(:notification?).and_return(true).twice
68
+ expect(Bullet).to receive(:notification?).and_return(true)
69
69
  expect(Bullet).to receive(:gather_inline_notifications).and_return("<bullet></bullet>")
70
70
  expect(Bullet).to receive(:perform_out_of_channel_notifications)
71
- status, headers, response = middleware.call([200, {"Content-Type" => "text/html"}])
71
+ status, headers, response = middleware.call({"Content-Type" => "text/html"})
72
72
  expect(headers["Content-Length"]).to eq("56")
73
- expect(response).to eq(["<html><head></head><body></body></html><bullet></bullet>"])
73
+ expect(response).to eq(["<html><head></head><body><bullet></bullet></body></html>"])
74
74
  end
75
75
 
76
76
  it "should set the right Content-Length if response body contains accents" do
77
77
  response = Support::ResponseDouble.new
78
78
  response.body = "<html><head></head><body>é</body></html>"
79
79
  app.response = response
80
- expect(Bullet).to receive(:notification?).and_return(true).twice
80
+ expect(Bullet).to receive(:notification?).and_return(true)
81
81
  expect(Bullet).to receive(:gather_inline_notifications).and_return("<bullet></bullet>")
82
- status, headers, response = middleware.call([200, {"Content-Type" => "text/html"}])
82
+ status, headers, response = middleware.call({"Content-Type" => "text/html"})
83
83
  expect(headers["Content-Length"]).to eq("58")
84
84
  end
85
85
  end
@@ -89,7 +89,38 @@ module Bullet
89
89
 
90
90
  it "should not call Bullet.start_request" do
91
91
  expect(Bullet).not_to receive(:start_request)
92
- middleware.call([])
92
+ middleware.call({})
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "#response_body" do
98
+ let(:response) { double }
99
+ let(:body_string) { "<html><body>My Body</body></html>" }
100
+
101
+ context "when `response` responds to `body`" do
102
+ before { allow(response).to receive(:body).and_return(body) }
103
+
104
+ context "when `body` returns an Array" do
105
+ let(:body) { [body_string, 'random string'] }
106
+ it "should return the plain body string" do
107
+ expect(middleware.response_body(response)).to eq body_string
108
+ end
109
+ end
110
+
111
+ context "when `body` does not return an Array" do
112
+ let(:body) { body_string }
113
+ it "should return the plain body string" do
114
+ expect(middleware.response_body(response)).to eq body_string
115
+ end
116
+ end
117
+ end
118
+
119
+ context "when `response` does not respond to `body`" do
120
+ before { allow(response).to receive(:first).and_return(body_string) }
121
+
122
+ it "should return the plain body string" do
123
+ expect(middleware.response_body(response)).to eq body_string
93
124
  end
94
125
  end
95
126
  end
data/spec/bullet_spec.rb CHANGED
@@ -38,4 +38,97 @@ describe Bullet, focused: true do
38
38
  end
39
39
  end
40
40
  end
41
+
42
+ describe '#start?' do
43
+ context 'when bullet is disabled' do
44
+ before(:each) do
45
+ Bullet.enable = false
46
+ end
47
+
48
+ it 'should not be started' do
49
+ expect(Bullet).not_to be_start
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '#debug' do
55
+ before(:each) do
56
+ $stdout = StringIO.new
57
+ end
58
+
59
+ after(:each) do
60
+ $stdout = STDOUT
61
+ end
62
+
63
+ context 'when debug is enabled' do
64
+ before(:each) do
65
+ ENV['BULLET_DEBUG'] = 'true'
66
+ end
67
+
68
+ after(:each) do
69
+ ENV['BULLET_DEBUG'] = 'false'
70
+ end
71
+
72
+ it 'should output debug information' do
73
+ Bullet.debug('debug_message', 'this is helpful information')
74
+
75
+ expect($stdout.string)
76
+ .to eq("[Bullet][debug_message] this is helpful information\n")
77
+ end
78
+ end
79
+
80
+ context 'when debug is disabled' do
81
+ it 'should output debug information' do
82
+ Bullet.debug('debug_message', 'this is helpful information')
83
+
84
+ expect($stdout.string).to be_empty
85
+ end
86
+ end
87
+ end
88
+
89
+ describe '#add_whitelist' do
90
+ context "for 'special' class names" do
91
+ it 'is added to the whitelist successfully' do
92
+ Bullet.add_whitelist(:type => :n_plus_one_query, :class_name => 'Klass', :association => :department)
93
+ expect(Bullet.get_whitelist_associations(:n_plus_one_query, 'Klass')).to include :department
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '#perform_out_of_channel_notifications' do
99
+ let(:notification) { double }
100
+
101
+ before do
102
+ allow(Bullet).to receive(:for_each_active_notifier_with_notification).and_yield(notification)
103
+ allow(notification).to receive(:notify_out_of_channel)
104
+ end
105
+
106
+ context 'when called with Rack environment hash' do
107
+ let(:env) {
108
+ {
109
+ 'REQUEST_METHOD' => 'GET',
110
+ 'PATH_INFO' => '/path',
111
+ 'QUERY_STRING' => 'foo=bar',
112
+ }
113
+ }
114
+
115
+ context "when env['REQUEST_URI'] is nil" do
116
+ before { env['REQUEST_URI'] = nil }
117
+
118
+ it 'should notification.url is built' do
119
+ expect(notification).to receive(:url=).with('GET /path?foo=bar')
120
+ Bullet.perform_out_of_channel_notifications(env)
121
+ end
122
+ end
123
+
124
+ context "when env['REQUEST_URI'] is present" do
125
+ before { env['REQUEST_URI'] = 'http://example.com/path' }
126
+
127
+ it "should notification.url is env['REQUEST_URI']" do
128
+ expect(notification).to receive(:url=).with('GET http://example.com/path')
129
+ Bullet.perform_out_of_channel_notifications(env)
130
+ end
131
+ end
132
+ end
133
+ end
41
134
  end
@@ -13,6 +13,16 @@ if !mongoid? && active_record4?
13
13
  expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
14
14
  end
15
15
 
16
+ it "should detect non preload post => comments for find_by_sql" do
17
+ Post.find_by_sql("SELECT * FROM posts").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_detecting_unpreloaded_association_for(Post, :comments)
24
+ end
25
+
16
26
  it "should detect preload with post => comments" do
17
27
  Post.includes(:comments).each do |post|
18
28
  post.comments.map(&:name)
@@ -72,6 +82,16 @@ if !mongoid? && active_record4?
72
82
 
73
83
  expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
74
84
  end
85
+
86
+ it "should not detect unused preload person => pets with empty?" do
87
+ Person.all.each do |person|
88
+ person.pets.empty?
89
+ end
90
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
91
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
92
+
93
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
94
+ end
75
95
  end
76
96
 
77
97
  context "category => posts => comments" do
@@ -204,7 +224,7 @@ if !mongoid? && active_record4?
204
224
  context "post => comment" do
205
225
  it "should detect unused preload with post => comments" do
206
226
  Post.includes(:comments).each do |post|
207
- post.comments.first.name
227
+ post.comments.first.name if post.comments.first
208
228
  end
209
229
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
210
230
  expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :comments)
@@ -219,6 +239,20 @@ if !mongoid? && active_record4?
219
239
 
220
240
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
221
241
  end
242
+
243
+ it "should not detect unused preload with category => posts" do
244
+ category = Category.first
245
+ category.draft_post.destroy!
246
+ post = category.draft_post
247
+ post.update_attributes!(link: true)
248
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
249
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
250
+
251
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
252
+
253
+ Support::SqliteSeed.setup_db
254
+ Support::SqliteSeed.seed_db
255
+ end
222
256
  end
223
257
 
224
258
  context "category => posts => writer" do
@@ -313,7 +347,7 @@ if !mongoid? && active_record4?
313
347
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
314
348
  end
315
349
 
316
- it "should detect unused preload with comments => post" do
350
+ it "should detect unused preload with comment => post" do
317
351
  Comment.includes(:post).map(&:name)
318
352
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
319
353
  expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Comment, :post)
@@ -333,6 +367,15 @@ if !mongoid? && active_record4?
333
367
  expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
334
368
  end
335
369
 
370
+ it "should not detect non preload association with only one comment" do
371
+ Comment.first.post.category.name
372
+
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
+
336
379
  it "should detect non preload association with post => category" do
337
380
  Comment.includes(:post).each do |comment|
338
381
  comment.post.category.name
@@ -432,6 +475,16 @@ if !mongoid? && active_record4?
432
475
 
433
476
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
434
477
  end
478
+
479
+ it "should detect non preload student => teachers with empty?" do
480
+ Student.all.each do |student|
481
+ student.teachers.empty?
482
+ end
483
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
484
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
485
+
486
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Student, :teachers)
487
+ end
435
488
  end
436
489
  end
437
490
 
@@ -515,6 +568,17 @@ if !mongoid? && active_record4?
515
568
  end
516
569
  end
517
570
 
571
+ describe Bullet::Detector::Association, "has_one => has_many" do
572
+ it "should not detect preload association" do
573
+ user = User.first
574
+ user.submission.replies.map(&:name)
575
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
576
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
577
+
578
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
579
+ end
580
+ end
581
+
518
582
  describe Bullet::Detector::Association, "call one association that in possible objects" do
519
583
  it "should not detect preload association" do
520
584
  Post.all
@@ -526,6 +590,50 @@ if !mongoid? && active_record4?
526
590
  end
527
591
  end
528
592
 
593
+ describe Bullet::Detector::Association, "query immediately after creation" do
594
+ context "with save" do
595
+ context "document => children" do
596
+ it 'should not detect non preload associations' do
597
+ document1 = Document.new
598
+ document1.children.build
599
+ document1.save
600
+
601
+ document2 = Document.new(parent: document1)
602
+ document2.save
603
+ document2.parent
604
+
605
+ document1.children.each.first
606
+
607
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
608
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
609
+
610
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
611
+ end
612
+ end
613
+ end
614
+
615
+ context "with save!" do
616
+ context "document => children" do
617
+ it 'should not detect non preload associations' do
618
+ document1 = Document.new
619
+ document1.children.build
620
+ document1.save!
621
+
622
+ document2 = Document.new(parent: document1)
623
+ document2.save!
624
+ document2.parent
625
+
626
+ document1.children.each.first
627
+
628
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
629
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
630
+
631
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
632
+ end
633
+ end
634
+ end
635
+ end
636
+
529
637
  describe Bullet::Detector::Association, "STI" do
530
638
  context "page => author" do
531
639
  it "should detect non preload associations" do
@@ -613,7 +721,7 @@ if !mongoid? && active_record4?
613
721
 
614
722
  context "whitelist n plus one query" do
615
723
  before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
616
- after { Bullet.reset_whitelist }
724
+ after { Bullet.clear_whitelist }
617
725
 
618
726
  it "should not detect n plus one query" do
619
727
  Post.all.each do |post|
@@ -636,7 +744,7 @@ if !mongoid? && active_record4?
636
744
 
637
745
  context "whitelist unused eager loading" do
638
746
  before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
639
- after { Bullet.reset_whitelist }
747
+ after { Bullet.clear_whitelist }
640
748
 
641
749
  it "should not detect unused eager loading" do
642
750
  Post.includes(:comments).map(&:name)