bullet 4.14.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +56 -1
  3. data/CHANGELOG.md +53 -0
  4. data/Gemfile.mongoid +0 -2
  5. data/Gemfile.mongoid-2.4 +2 -4
  6. data/Gemfile.mongoid-2.5 +2 -4
  7. data/Gemfile.mongoid-2.6 +1 -3
  8. data/Gemfile.mongoid-2.7 +2 -4
  9. data/Gemfile.mongoid-2.8 +2 -4
  10. data/Gemfile.mongoid-3.0 +2 -4
  11. data/Gemfile.mongoid-3.1 +2 -4
  12. data/Gemfile.mongoid-4.0 +1 -3
  13. data/Gemfile.mongoid-5.0 +17 -0
  14. data/Gemfile.rails-3.0 +1 -3
  15. data/Gemfile.rails-3.1 +1 -3
  16. data/Gemfile.rails-3.2 +1 -3
  17. data/Gemfile.rails-4.0 +1 -3
  18. data/Gemfile.rails-4.1 +1 -3
  19. data/Gemfile.rails-4.2 +1 -3
  20. data/Gemfile.rails-5.0 +17 -0
  21. data/README.md +31 -2
  22. data/bullet.gemspec +1 -1
  23. data/lib/bullet/active_record3.rb +65 -35
  24. data/lib/bullet/active_record3x.rb +54 -32
  25. data/lib/bullet/active_record4.rb +62 -30
  26. data/lib/bullet/active_record41.rb +63 -32
  27. data/lib/bullet/active_record42.rb +105 -40
  28. data/lib/bullet/active_record5.rb +217 -0
  29. data/lib/bullet/dependency.rb +16 -0
  30. data/lib/bullet/detector/association.rb +16 -16
  31. data/lib/bullet/detector/counter_cache.rb +13 -13
  32. data/lib/bullet/detector/n_plus_one_query.rb +33 -24
  33. data/lib/bullet/detector/unused_eager_loading.rb +1 -1
  34. data/lib/bullet/ext/object.rb +3 -1
  35. data/lib/bullet/mongoid5x.rb +56 -0
  36. data/lib/bullet/notification/base.rb +1 -1
  37. data/lib/bullet/notification/n_plus_one_query.rb +6 -0
  38. data/lib/bullet/rack.rb +19 -11
  39. data/lib/bullet/version.rb +1 -1
  40. data/lib/bullet.rb +28 -11
  41. data/spec/bullet/detector/counter_cache_spec.rb +8 -8
  42. data/spec/bullet/detector/n_plus_one_query_spec.rb +42 -27
  43. data/spec/bullet/ext/object_spec.rb +6 -0
  44. data/spec/bullet/notification/base_spec.rb +2 -2
  45. data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -3
  46. data/spec/bullet/notification/unused_eager_loading_spec.rb +1 -1
  47. data/spec/bullet/rack_spec.rb +3 -3
  48. data/spec/bullet_spec.rb +47 -0
  49. data/spec/integration/active_record3/association_spec.rb +11 -2
  50. data/spec/integration/active_record4/association_spec.rb +58 -3
  51. data/spec/integration/active_record5/association_spec.rb +715 -0
  52. data/spec/integration/counter_cache_spec.rb +17 -1
  53. data/spec/models/category.rb +4 -1
  54. data/spec/models/comment.rb +2 -0
  55. data/spec/models/post.rb +7 -2
  56. data/spec/models/reply.rb +3 -0
  57. data/spec/models/submission.rb +1 -1
  58. data/spec/spec_helper.rb +3 -2
  59. data/spec/support/mongo_seed.rb +13 -0
  60. data/spec/support/sqlite_seed.rb +14 -6
  61. data/test.sh +1 -0
  62. data/update.sh +15 -0
  63. metadata +16 -7
@@ -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
@@ -5,9 +5,9 @@ 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\n") }
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\n", " Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2\n" ]) }
10
- it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]") }
8
+ it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call 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]\nN+1 Query method call stack\n caller1\n caller2\n", " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call 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
11
  it { expect(subject.title).to eq("N+1 Query in path") }
12
12
  end
13
13
  end
@@ -5,7 +5,7 @@ module Bullet
5
5
  describe UnusedEagerLoading do
6
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]") }
8
+ it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :includes => [:comments, :votes]") }
9
9
  it { expect(subject.title).to eq("Unused Eager Loading in path") }
10
10
  end
11
11
  end
@@ -65,19 +65,19 @@ module Bullet
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
71
  status, headers, response = middleware.call([200, {"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
82
  status, headers, response = middleware.call([200, {"Content-Type" => "text/html"}])
83
83
  expect(headers["Content-Length"]).to eq("58")
data/spec/bullet_spec.rb CHANGED
@@ -38,4 +38,51 @@ 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
41
88
  end
@@ -335,6 +335,15 @@ if !mongoid? && active_record3?
335
335
  expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
336
336
  end
337
337
 
338
+ it "should not detect non preload association with only one comment" do
339
+ Comment.first.post.category.name
340
+
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
+
338
347
  it "should detect non preload association with post => category" do
339
348
  Comment.includes(:post).each do |comment|
340
349
  comment.post.category.name
@@ -615,7 +624,7 @@ if !mongoid? && active_record3?
615
624
 
616
625
  context "whitelist n plus one query" do
617
626
  before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
618
- after { Bullet.reset_whitelist }
627
+ after { Bullet.clear_whitelist }
619
628
 
620
629
  it "should not detect n plus one query" do
621
630
  Post.all.each do |post|
@@ -638,7 +647,7 @@ if !mongoid? && active_record3?
638
647
 
639
648
  context "whitelist unused eager loading" do
640
649
  before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
641
- after { Bullet.reset_whitelist }
650
+ after { Bullet.clear_whitelist }
642
651
 
643
652
  it "should not detect unused eager loading" do
644
653
  Post.includes(:comments).map(&:name)
@@ -219,6 +219,20 @@ if !mongoid? && active_record4?
219
219
 
220
220
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
221
221
  end
222
+
223
+ it "should not detect unused preload with category => posts" do
224
+ category = Category.first
225
+ category.draft_post.destroy!
226
+ post = category.draft_post
227
+ post.update_attributes!(link: true)
228
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
229
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
230
+
231
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
232
+
233
+ Support::SqliteSeed.setup_db
234
+ Support::SqliteSeed.seed_db
235
+ end
222
236
  end
223
237
 
224
238
  context "category => posts => writer" do
@@ -313,7 +327,7 @@ if !mongoid? && active_record4?
313
327
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
314
328
  end
315
329
 
316
- it "should detect unused preload with comments => post" do
330
+ it "should detect unused preload with comment => post" do
317
331
  Comment.includes(:post).map(&:name)
318
332
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
319
333
  expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Comment, :post)
@@ -333,6 +347,15 @@ if !mongoid? && active_record4?
333
347
  expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
334
348
  end
335
349
 
350
+ it "should not detect non preload association with only one comment" do
351
+ Comment.first.post.category.name
352
+
353
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
354
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
355
+
356
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
357
+ end
358
+
336
359
  it "should detect non preload association with post => category" do
337
360
  Comment.includes(:post).each do |comment|
338
361
  comment.post.category.name
@@ -515,6 +538,17 @@ if !mongoid? && active_record4?
515
538
  end
516
539
  end
517
540
 
541
+ describe Bullet::Detector::Association, "has_one => has_many" do
542
+ it "should not detect preload association" do
543
+ user = User.first
544
+ user.submission.replies.map(&:name)
545
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
546
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
547
+
548
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
549
+ end
550
+ end
551
+
518
552
  describe Bullet::Detector::Association, "call one association that in possible objects" do
519
553
  it "should not detect preload association" do
520
554
  Post.all
@@ -526,6 +560,27 @@ if !mongoid? && active_record4?
526
560
  end
527
561
  end
528
562
 
563
+ describe Bullet::Detector::Association, "query immediately after creation" do
564
+ context "document => children" do
565
+ it 'should not detect non preload associations' do
566
+ document1 = Document.new
567
+ document1.children.build
568
+ document1.save
569
+
570
+ document2 = Document.new(parent: document1)
571
+ document2.save
572
+ document2.parent
573
+
574
+ document1.children.each.first
575
+
576
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
577
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
578
+
579
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
580
+ end
581
+ end
582
+ end
583
+
529
584
  describe Bullet::Detector::Association, "STI" do
530
585
  context "page => author" do
531
586
  it "should detect non preload associations" do
@@ -613,7 +668,7 @@ if !mongoid? && active_record4?
613
668
 
614
669
  context "whitelist n plus one query" do
615
670
  before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
616
- after { Bullet.reset_whitelist }
671
+ after { Bullet.clear_whitelist }
617
672
 
618
673
  it "should not detect n plus one query" do
619
674
  Post.all.each do |post|
@@ -636,7 +691,7 @@ if !mongoid? && active_record4?
636
691
 
637
692
  context "whitelist unused eager loading" do
638
693
  before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
639
- after { Bullet.reset_whitelist }
694
+ after { Bullet.clear_whitelist }
640
695
 
641
696
  it "should not detect unused eager loading" do
642
697
  Post.includes(:comments).map(&:name)