bullet 5.7.0 → 5.8.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -1
  3. data/Gemfile.rails-5.2 +1 -1
  4. data/Guardfile +1 -1
  5. data/README.md +9 -4
  6. data/Rakefile +5 -5
  7. data/bullet.gemspec +11 -6
  8. data/lib/bullet/active_record4.rb +18 -14
  9. data/lib/bullet/active_record41.rb +16 -14
  10. data/lib/bullet/active_record42.rb +24 -22
  11. data/lib/bullet/active_record5.rb +78 -49
  12. data/lib/bullet/active_record52.rb +47 -40
  13. data/lib/bullet/dependency.rb +3 -1
  14. data/lib/bullet/detector/association.rb +16 -14
  15. data/lib/bullet/detector/base.rb +2 -0
  16. data/lib/bullet/detector/counter_cache.rb +10 -7
  17. data/lib/bullet/detector/n_plus_one_query.rb +17 -15
  18. data/lib/bullet/detector/unused_eager_loading.rb +26 -21
  19. data/lib/bullet/detector.rb +2 -0
  20. data/lib/bullet/ext/object.rb +6 -4
  21. data/lib/bullet/ext/string.rb +3 -1
  22. data/lib/bullet/mongoid4x.rb +7 -2
  23. data/lib/bullet/mongoid5x.rb +7 -2
  24. data/lib/bullet/mongoid6x.rb +11 -6
  25. data/lib/bullet/notification/base.rb +21 -15
  26. data/lib/bullet/notification/counter_cache.rb +2 -0
  27. data/lib/bullet/notification/n_plus_one_query.rb +6 -4
  28. data/lib/bullet/notification/unused_eager_loading.rb +6 -4
  29. data/lib/bullet/notification.rb +2 -0
  30. data/lib/bullet/notification_collector.rb +2 -1
  31. data/lib/bullet/rack.rb +19 -15
  32. data/lib/bullet/registry/association.rb +2 -0
  33. data/lib/bullet/registry/base.rb +2 -0
  34. data/lib/bullet/registry/object.rb +2 -0
  35. data/lib/bullet/registry.rb +2 -0
  36. data/lib/bullet/stack_trace_filter.rb +56 -19
  37. data/lib/bullet/version.rb +2 -1
  38. data/lib/bullet.rb +31 -29
  39. data/lib/generators/bullet/install_generator.rb +5 -3
  40. data/perf/benchmark.rb +9 -7
  41. data/rails/init.rb +2 -0
  42. data/spec/bullet/detector/association_spec.rb +2 -0
  43. data/spec/bullet/detector/base_spec.rb +2 -0
  44. data/spec/bullet/detector/counter_cache_spec.rb +2 -0
  45. data/spec/bullet/detector/n_plus_one_query_spec.rb +33 -8
  46. data/spec/bullet/detector/unused_eager_loading_spec.rb +2 -0
  47. data/spec/bullet/ext/object_spec.rb +3 -1
  48. data/spec/bullet/ext/string_spec.rb +2 -0
  49. data/spec/bullet/notification/base_spec.rb +8 -6
  50. data/spec/bullet/notification/counter_cache_spec.rb +3 -1
  51. data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -1
  52. data/spec/bullet/notification/unused_eager_loading_spec.rb +3 -1
  53. data/spec/bullet/notification_collector_spec.rb +2 -0
  54. data/spec/bullet/rack_spec.rb +10 -9
  55. data/spec/bullet/registry/association_spec.rb +4 -2
  56. data/spec/bullet/registry/base_spec.rb +5 -3
  57. data/spec/bullet/registry/object_spec.rb +2 -0
  58. data/spec/bullet_spec.rb +9 -7
  59. data/spec/integration/active_record/association_spec.rb +79 -17
  60. data/spec/integration/counter_cache_spec.rb +4 -2
  61. data/spec/integration/mongoid/association_spec.rb +2 -0
  62. data/spec/models/address.rb +2 -0
  63. data/spec/models/author.rb +2 -0
  64. data/spec/models/base_user.rb +2 -0
  65. data/spec/models/category.rb +2 -0
  66. data/spec/models/city.rb +2 -0
  67. data/spec/models/client.rb +4 -0
  68. data/spec/models/comment.rb +2 -0
  69. data/spec/models/company.rb +2 -0
  70. data/spec/models/country.rb +2 -0
  71. data/spec/models/document.rb +2 -0
  72. data/spec/models/entry.rb +2 -0
  73. data/spec/models/firm.rb +3 -0
  74. data/spec/models/folder.rb +2 -0
  75. data/spec/models/group.rb +4 -0
  76. data/spec/models/mongoid/address.rb +3 -1
  77. data/spec/models/mongoid/category.rb +4 -2
  78. data/spec/models/mongoid/comment.rb +3 -1
  79. data/spec/models/mongoid/company.rb +3 -1
  80. data/spec/models/mongoid/entry.rb +3 -1
  81. data/spec/models/mongoid/post.rb +6 -4
  82. data/spec/models/mongoid/user.rb +2 -0
  83. data/spec/models/newspaper.rb +2 -0
  84. data/spec/models/page.rb +2 -0
  85. data/spec/models/person.rb +2 -0
  86. data/spec/models/pet.rb +2 -0
  87. data/spec/models/post.rb +17 -0
  88. data/spec/models/relationship.rb +2 -0
  89. data/spec/models/reply.rb +2 -0
  90. data/spec/models/student.rb +2 -0
  91. data/spec/models/submission.rb +2 -0
  92. data/spec/models/teacher.rb +2 -0
  93. data/spec/models/user.rb +2 -0
  94. data/spec/models/writer.rb +2 -0
  95. data/spec/spec_helper.rb +3 -1
  96. data/spec/support/bullet_ext.rb +2 -0
  97. data/spec/support/mongo_seed.rb +32 -30
  98. data/spec/support/rack_double.rb +9 -16
  99. data/spec/support/sqlite_seed.rb +84 -75
  100. data/tasks/bullet_tasks.rake +2 -0
  101. metadata +11 -7
data/spec/models/city.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class City < ActiveRecord::Base
2
4
  belongs_to :country
3
5
  end
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Client < ActiveRecord::Base
4
+ belongs_to :group
5
+
2
6
  has_many :relationships
3
7
  has_many :firms, through: :relationships
4
8
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Comment < ActiveRecord::Base
2
4
  belongs_to :post, inverse_of: :comments
3
5
  belongs_to :author, class_name: 'BaseUser'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Company < ActiveRecord::Base
2
4
  has_one :address
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Country < ActiveRecord::Base
2
4
  has_many :cities
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Document < ActiveRecord::Base
2
4
  has_many :children, class_name: 'Document', foreign_key: 'parent_id'
3
5
  belongs_to :parent, class_name: 'Document', foreign_key: 'parent_id'
data/spec/models/entry.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Entry < ActiveRecord::Base
2
4
  belongs_to :category
3
5
  end
data/spec/models/firm.rb CHANGED
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Firm < ActiveRecord::Base
2
4
  has_many :relationships
3
5
  has_many :clients, through: :relationships
6
+ has_many :groups, through: :clients
4
7
  end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Folder < Document
2
4
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Group < ActiveRecord::Base
4
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Mongoid::Address
2
4
  include Mongoid::Document
3
5
 
4
6
  field :name
5
7
 
6
- belongs_to :company, :class_name => 'Mongoid::Company'
8
+ belongs_to :company, class_name: 'Mongoid::Company'
7
9
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Mongoid::Category
2
4
  include Mongoid::Document
3
5
 
4
6
  field :name
5
7
 
6
- has_many :posts, :class_name => 'Mongoid::Post'
7
- has_many :entries, :class_name => 'Mongoid::Entry'
8
+ has_many :posts, class_name: 'Mongoid::Post'
9
+ has_many :entries, class_name: 'Mongoid::Entry'
8
10
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Mongoid::Comment
2
4
  include Mongoid::Document
3
5
 
4
6
  field :name
5
7
 
6
- belongs_to :post, :class_name => 'Mongoid::Post'
8
+ belongs_to :post, class_name: 'Mongoid::Post'
7
9
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Mongoid::Company
2
4
  include Mongoid::Document
3
5
 
4
6
  field :name
5
7
 
6
- has_one :address, :class_name => 'Mongoid::Address'
8
+ has_one :address, class_name: 'Mongoid::Address'
7
9
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Mongoid::Entry
2
4
  include Mongoid::Document
3
5
 
4
6
  field :name
5
7
 
6
- belongs_to :category, :class_name => 'Mongoid::Category'
8
+ belongs_to :category, class_name: 'Mongoid::Category'
7
9
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Mongoid::Post
2
4
  include Mongoid::Document
3
5
 
4
6
  field :name
5
7
 
6
- has_many :comments, :class_name => 'Mongoid::Comment'
7
- belongs_to :category, :class_name => 'Mongoid::Category'
8
+ has_many :comments, class_name: 'Mongoid::Comment'
9
+ belongs_to :category, class_name: 'Mongoid::Category'
8
10
 
9
- embeds_many :users, :class_name => 'Mongoid::User'
11
+ embeds_many :users, class_name: 'Mongoid::User'
10
12
 
11
- scope :preload_comments, lambda { includes(:comments) }
13
+ scope :preload_comments, -> { includes(:comments) }
12
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Mongoid::User
2
4
  include Mongoid::Document
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Newspaper < ActiveRecord::Base
2
4
  has_many :writers, class_name: 'BaseUser'
3
5
  end
data/spec/models/page.rb CHANGED
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Page < Document
2
4
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Person < ActiveRecord::Base
2
4
  has_many :pets
3
5
  end
data/spec/models/pet.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pet < ActiveRecord::Base
2
4
  belongs_to :person, counter_cache: true
3
5
  end
data/spec/models/post.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Post < ActiveRecord::Base
2
4
  belongs_to :category, inverse_of: :posts
3
5
  belongs_to :writer
@@ -12,4 +14,19 @@ class Post < ActiveRecord::Base
12
14
  def link=(*)
13
15
  comments.new
14
16
  end
17
+
18
+ # see association_spec.rb 'should not detect newly assigned object in an after_save'
19
+ attr_accessor :trigger_after_save
20
+ after_save do
21
+ next unless trigger_after_save
22
+
23
+ temp_comment = Comment.new(post: self)
24
+ # this triggers self to be "possible", even though it's
25
+ # not saved yet
26
+ temp_comment.post
27
+
28
+ # category should NOT whine about not being pre-loaded, because
29
+ # it's obviously attached to a new object
30
+ category
31
+ end
15
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Relationship < ActiveRecord::Base
2
4
  belongs_to :firm
3
5
  belongs_to :client
data/spec/models/reply.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Reply < ActiveRecord::Base
2
4
  belongs_to :submission
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Student < ActiveRecord::Base
2
4
  has_and_belongs_to_many :teachers
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Submission < ActiveRecord::Base
2
4
  belongs_to :user
3
5
  has_many :replies
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Teacher < ActiveRecord::Base
2
4
  has_and_belongs_to_many :students
3
5
  end
data/spec/models/user.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class User < ActiveRecord::Base
2
4
  has_one :submission
3
5
  belongs_to :category
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Writer < BaseUser
2
4
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rspec'
2
4
  begin
3
5
  require 'active_record'
@@ -33,7 +35,7 @@ Dir[File.join(SUPPORT, '*.rb')].reject { |filename| filename =~ /_seed.rb$/ }.so
33
35
  RSpec.configure do |config|
34
36
  config.extend Bullet::Dependency
35
37
 
36
- config.filter_run :focus => true
38
+ config.filter_run focus: true
37
39
  config.run_all_when_everything_filtered = true
38
40
  end
39
41
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bullet
2
4
  def self.collected_notifications_of_class(notification_class)
3
5
  Bullet.notification_collector.collection.select do |notification|
@@ -1,35 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Support
2
4
  module MongoSeed
5
+ module_function
6
+
3
7
  def seed_db
4
- category1 = Mongoid::Category.create(:name => 'first')
5
- category2 = Mongoid::Category.create(:name => 'second')
8
+ category1 = Mongoid::Category.create(name: 'first')
9
+ category2 = Mongoid::Category.create(name: 'second')
6
10
 
7
- post1 = category1.posts.create(:name => 'first')
8
- post1a = category1.posts.create(:name => 'like first')
9
- post2 = category2.posts.create(:name => 'second')
11
+ post1 = category1.posts.create(name: 'first')
12
+ post1a = category1.posts.create(name: 'like first')
13
+ post2 = category2.posts.create(name: 'second')
10
14
 
11
- post1.users << Mongoid::User.create(:name => 'first')
12
- post1.users << Mongoid::User.create(:name => 'another')
13
- post2.users << Mongoid::User.create(:name => 'second')
15
+ post1.users << Mongoid::User.create(name: 'first')
16
+ post1.users << Mongoid::User.create(name: 'another')
17
+ post2.users << Mongoid::User.create(name: 'second')
14
18
 
15
- comment1 = post1.comments.create(:name => 'first')
16
- comment2 = post1.comments.create(:name => 'first2')
17
- comment3 = post1.comments.create(:name => 'first3')
18
- comment4 = post1.comments.create(:name => 'second')
19
- comment8 = post1a.comments.create(:name => 'like first 1')
20
- comment9 = post1a.comments.create(:name => 'like first 2')
21
- comment5 = post2.comments.create(:name => 'third')
22
- comment6 = post2.comments.create(:name => 'fourth')
23
- comment7 = post2.comments.create(:name => 'fourth')
19
+ comment1 = post1.comments.create(name: 'first')
20
+ comment2 = post1.comments.create(name: 'first2')
21
+ comment3 = post1.comments.create(name: 'first3')
22
+ comment4 = post1.comments.create(name: 'second')
23
+ comment8 = post1a.comments.create(name: 'like first 1')
24
+ comment9 = post1a.comments.create(name: 'like first 2')
25
+ comment5 = post2.comments.create(name: 'third')
26
+ comment6 = post2.comments.create(name: 'fourth')
27
+ comment7 = post2.comments.create(name: 'fourth')
24
28
 
25
- entry1 = category1.entries.create(:name => 'first')
26
- entry2 = category1.entries.create(:name => 'second')
29
+ entry1 = category1.entries.create(name: 'first')
30
+ entry2 = category1.entries.create(name: 'second')
27
31
 
28
- company1 = Mongoid::Company.create(:name => 'first')
29
- company2 = Mongoid::Company.create(:name => 'second')
32
+ company1 = Mongoid::Company.create(name: 'first')
33
+ company2 = Mongoid::Company.create(name: 'second')
30
34
 
31
- Mongoid::Address.create(:name => 'first', :company => company1)
32
- Mongoid::Address.create(:name => 'second', :company => company2)
35
+ Mongoid::Address.create(name: 'first', company: company1)
36
+ Mongoid::Address.create(name: 'second', company: company2)
33
37
  end
34
38
 
35
39
  def setup_db
@@ -47,12 +51,12 @@ module Support
47
51
  else
48
52
  Mongoid.configure do |config|
49
53
  config.load_configuration(
50
- clients: {
51
- default: {
52
- database: 'bullet',
53
- hosts: ['localhost:27017']
54
- }
54
+ clients: {
55
+ default: {
56
+ database: 'bullet',
57
+ hosts: ['localhost:27017']
55
58
  }
59
+ }
56
60
  )
57
61
  end
58
62
  # Increase the level from DEBUG in order to avoid excessive logging to the screen
@@ -64,7 +68,5 @@ module Support
64
68
  Mongoid.purge!
65
69
  Mongoid::IdentityMap.clear if Mongoid.const_defined?(:IdentityMap)
66
70
  end
67
-
68
- extend self
69
71
  end
70
72
  end
@@ -1,26 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Support
2
4
  class AppDouble
3
- def call env
5
+ def call(_env)
4
6
  env = @env
5
7
  [status, headers, response]
6
8
  end
7
9
 
8
- def status= status
9
- @status = status
10
- end
10
+ attr_writer :status
11
11
 
12
- def headers= headers
13
- @headers = headers
14
- end
12
+ attr_writer :headers
15
13
 
16
14
  def headers
17
15
  @headers ||= { 'Content-Type' => 'text/html' }
18
16
  @headers
19
17
  end
20
18
 
21
- def response= response
22
- @response = response
23
- end
19
+ attr_writer :response
24
20
 
25
21
  private
26
22
 
@@ -34,7 +30,7 @@ module Support
34
30
  end
35
31
 
36
32
  class ResponseDouble
37
- def initialize actual_body = nil
33
+ def initialize(actual_body = nil)
38
34
  @actual_body = actual_body
39
35
  end
40
36
 
@@ -42,15 +38,12 @@ module Support
42
38
  @body ||= '<html><head></head><body></body></html>'
43
39
  end
44
40
 
45
- def body= body
46
- @body = body
47
- end
41
+ attr_writer :body
48
42
 
49
43
  def each
50
44
  yield body
51
45
  end
52
46
 
53
- def close
54
- end
47
+ def close; end
55
48
  end
56
49
  end