bullet 6.0.1 → 6.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -1
  3. data/CHANGELOG.md +25 -0
  4. data/Gemfile.rails-6.0 +1 -1
  5. data/Gemfile.rails-6.1 +15 -0
  6. data/README.md +12 -3
  7. data/lib/bullet.rb +30 -19
  8. data/lib/bullet/active_job.rb +1 -3
  9. data/lib/bullet/active_record4.rb +9 -23
  10. data/lib/bullet/active_record41.rb +7 -19
  11. data/lib/bullet/active_record42.rb +8 -16
  12. data/lib/bullet/active_record5.rb +188 -170
  13. data/lib/bullet/active_record52.rb +187 -161
  14. data/lib/bullet/active_record60.rb +204 -171
  15. data/lib/bullet/active_record61.rb +278 -0
  16. data/lib/bullet/bullet_xhr.js +17 -23
  17. data/lib/bullet/dependency.rb +42 -34
  18. data/lib/bullet/detector/association.rb +24 -18
  19. data/lib/bullet/detector/base.rb +1 -2
  20. data/lib/bullet/detector/counter_cache.rb +10 -6
  21. data/lib/bullet/detector/n_plus_one_query.rb +18 -8
  22. data/lib/bullet/detector/unused_eager_loading.rb +5 -2
  23. data/lib/bullet/mongoid4x.rb +3 -7
  24. data/lib/bullet/mongoid5x.rb +3 -7
  25. data/lib/bullet/mongoid6x.rb +3 -7
  26. data/lib/bullet/mongoid7x.rb +3 -7
  27. data/lib/bullet/notification/base.rb +14 -18
  28. data/lib/bullet/notification/n_plus_one_query.rb +2 -4
  29. data/lib/bullet/notification/unused_eager_loading.rb +2 -4
  30. data/lib/bullet/rack.rb +22 -14
  31. data/lib/bullet/stack_trace_filter.rb +5 -11
  32. data/lib/bullet/version.rb +1 -1
  33. data/lib/generators/bullet/install_generator.rb +23 -23
  34. data/perf/benchmark.rb +8 -14
  35. data/spec/bullet/detector/counter_cache_spec.rb +6 -6
  36. data/spec/bullet/detector/n_plus_one_query_spec.rb +7 -3
  37. data/spec/bullet/detector/unused_eager_loading_spec.rb +19 -6
  38. data/spec/bullet/notification/base_spec.rb +1 -3
  39. data/spec/bullet/notification/n_plus_one_query_spec.rb +16 -3
  40. data/spec/bullet/notification/unused_eager_loading_spec.rb +5 -1
  41. data/spec/bullet/rack_spec.rb +77 -7
  42. data/spec/bullet/registry/association_spec.rb +2 -2
  43. data/spec/bullet/registry/base_spec.rb +1 -1
  44. data/spec/bullet_spec.rb +10 -29
  45. data/spec/integration/active_record/association_spec.rb +77 -122
  46. data/spec/integration/counter_cache_spec.rb +10 -30
  47. data/spec/integration/mongoid/association_spec.rb +18 -32
  48. data/spec/models/attachment.rb +5 -0
  49. data/spec/models/folder.rb +1 -2
  50. data/spec/models/group.rb +1 -2
  51. data/spec/models/page.rb +1 -2
  52. data/spec/models/submission.rb +1 -0
  53. data/spec/models/user.rb +1 -0
  54. data/spec/models/writer.rb +1 -2
  55. data/spec/spec_helper.rb +6 -10
  56. data/spec/support/bullet_ext.rb +8 -9
  57. data/spec/support/mongo_seed.rb +2 -16
  58. data/spec/support/sqlite_seed.rb +8 -0
  59. metadata +10 -6
@@ -4,25 +4,17 @@ require 'spec_helper'
4
4
 
5
5
  if !mongoid? && active_record?
6
6
  describe Bullet::Detector::CounterCache do
7
- before(:each) do
8
- Bullet.start_request
9
- end
7
+ before(:each) { Bullet.start_request }
10
8
 
11
- after(:each) do
12
- Bullet.end_request
13
- end
9
+ after(:each) { Bullet.end_request }
14
10
 
15
11
  it 'should need counter cache with all cities' do
16
- Country.all.each do |country|
17
- country.cities.size
18
- end
12
+ Country.all.each { |country| country.cities.size }
19
13
  expect(Bullet.collected_counter_cache_notifications).not_to be_empty
20
14
  end
21
15
 
22
16
  it 'should not need counter cache if already define counter_cache' do
23
- Person.all.each do |person|
24
- person.pets.size
25
- end
17
+ Person.all.each { |person| person.pets.size }
26
18
  expect(Bullet.collected_counter_cache_notifications).to be_empty
27
19
  end
28
20
 
@@ -32,32 +24,24 @@ if !mongoid? && active_record?
32
24
  end
33
25
 
34
26
  it 'should not need counter cache without size' do
35
- Country.includes(:cities).each do |country|
36
- country.cities.empty?
37
- end
27
+ Country.includes(:cities).each { |country| country.cities.empty? }
38
28
  expect(Bullet.collected_counter_cache_notifications).to be_empty
39
29
  end
40
30
 
41
31
  if active_record5? || active_record6?
42
32
  it 'should not need counter cache for has_many through' do
43
- Client.all.each do |client|
44
- client.firms.size
45
- end
33
+ Client.all.each { |client| client.firms.size }
46
34
  expect(Bullet.collected_counter_cache_notifications).to be_empty
47
35
  end
48
36
  else
49
37
  it 'should need counter cache for has_many through' do
50
- Client.all.each do |client|
51
- client.firms.size
52
- end
38
+ Client.all.each { |client| client.firms.size }
53
39
  expect(Bullet.collected_counter_cache_notifications).not_to be_empty
54
40
  end
55
41
  end
56
42
 
57
43
  it 'should not need counter cache with part of cities' do
58
- Country.all.each do |country|
59
- country.cities.where(name: 'first').size
60
- end
44
+ Country.all.each { |country| country.cities.where(name: 'first').size }
61
45
  expect(Bullet.collected_counter_cache_notifications).to be_empty
62
46
  end
63
47
 
@@ -66,9 +50,7 @@ if !mongoid? && active_record?
66
50
  after { Bullet.counter_cache_enable = true }
67
51
 
68
52
  it 'should not detect counter cache' do
69
- Country.all.each do |country|
70
- country.cities.size
71
- end
53
+ Country.all.each { |country| country.cities.size }
72
54
  expect(Bullet.collected_counter_cache_notifications).to be_empty
73
55
  end
74
56
  end
@@ -78,9 +60,7 @@ if !mongoid? && active_record?
78
60
  after { Bullet.clear_whitelist }
79
61
 
80
62
  it 'should not detect counter cache' do
81
- Country.all.each do |country|
82
- country.cities.size
83
- end
63
+ Country.all.each { |country| country.cities.size }
84
64
  expect(Bullet.collected_counter_cache_notifications).to be_empty
85
65
  end
86
66
  end
@@ -7,9 +7,7 @@ if mongoid?
7
7
  context 'embeds_many' do
8
8
  context 'posts => users' do
9
9
  it 'should detect nothing' do
10
- Mongoid::Post.all.each do |post|
11
- post.users.map(&:name)
12
- end
10
+ Mongoid::Post.all.each { |post| post.users.map(&:name) }
13
11
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
14
12
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
15
13
 
@@ -21,9 +19,7 @@ if mongoid?
21
19
  context 'has_many' do
22
20
  context 'posts => comments' do
23
21
  it 'should detect non preload posts => comments' do
24
- Mongoid::Post.all.each do |post|
25
- post.comments.map(&:name)
26
- end
22
+ Mongoid::Post.all.each { |post| post.comments.map(&:name) }
27
23
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
28
24
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
29
25
 
@@ -31,9 +27,7 @@ if mongoid?
31
27
  end
32
28
 
33
29
  it 'should detect preload post => comments' do
34
- Mongoid::Post.includes(:comments).each do |post|
35
- post.comments.map(&:name)
36
- end
30
+ Mongoid::Post.includes(:comments).each { |post| post.comments.map(&:name) }
37
31
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
38
32
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
39
33
 
@@ -78,7 +72,10 @@ if mongoid?
78
72
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
79
73
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
80
74
 
81
- expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Mongoid::Category, :posts)
75
+ expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(
76
+ Mongoid::Category,
77
+ :posts
78
+ )
82
79
  expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Mongoid::Category, :entries)
83
80
  end
84
81
 
@@ -103,9 +100,7 @@ if mongoid?
103
100
  end
104
101
 
105
102
  it 'should detect unused preload with category => entries, but not with category => posts' do
106
- Mongoid::Category.includes(:posts, :entries).each do |category|
107
- category.posts.map(&:name)
108
- end
103
+ Mongoid::Category.includes(:posts, :entries).each { |category| category.posts.map(&:name) }
109
104
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
110
105
  expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Mongoid::Category, :posts)
111
106
  expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Mongoid::Category, :entries)
@@ -116,9 +111,7 @@ if mongoid?
116
111
 
117
112
  context 'post => comment' do
118
113
  it 'should detect unused preload with post => comments' do
119
- Mongoid::Post.includes(:comments).each do |post|
120
- post.comments.first.name
121
- end
114
+ Mongoid::Post.includes(:comments).each { |post| post.comments.first.name }
122
115
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
123
116
  expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Mongoid::Post, :comments)
124
117
 
@@ -136,9 +129,7 @@ if mongoid?
136
129
 
137
130
  context 'scope preload_comments' do
138
131
  it 'should detect preload post => comments with scope' do
139
- Mongoid::Post.preload_comments.each do |post|
140
- post.comments.map(&:name)
141
- end
132
+ Mongoid::Post.preload_comments.each { |post| post.comments.map(&:name) }
142
133
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
143
134
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
144
135
 
@@ -158,9 +149,7 @@ if mongoid?
158
149
  context 'belongs_to' do
159
150
  context 'comment => post' do
160
151
  it 'should detect non preload with comment => post' do
161
- Mongoid::Comment.all.each do |comment|
162
- comment.post.name
163
- end
152
+ Mongoid::Comment.all.each { |comment| comment.post.name }
164
153
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
165
154
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
166
155
 
@@ -176,9 +165,7 @@ if mongoid?
176
165
  end
177
166
 
178
167
  it 'should detect preload with comment => post' do
179
- Mongoid::Comment.includes(:post).each do |comment|
180
- comment.post.name
181
- end
168
+ Mongoid::Comment.includes(:post).each { |comment| comment.post.name }
182
169
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
183
170
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
184
171
 
@@ -207,20 +194,19 @@ if mongoid?
207
194
  context 'company => address' do
208
195
  if Mongoid::VERSION !~ /\A3.0/
209
196
  it 'should detect non preload association' do
210
- Mongoid::Company.all.each do |company|
211
- company.address.name
212
- end
197
+ Mongoid::Company.all.each { |company| company.address.name }
213
198
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
214
199
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
215
200
 
216
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Mongoid::Company, :address)
201
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(
202
+ Mongoid::Company,
203
+ :address
204
+ )
217
205
  end
218
206
  end
219
207
 
220
208
  it 'should detect preload association' do
221
- Mongoid::Company.includes(:address).each do |company|
222
- company.address.name
223
- end
209
+ Mongoid::Company.includes(:address).each { |company| company.address.name }
224
210
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
225
211
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
226
212
 
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Attachment < ActiveRecord::Base
4
+ belongs_to :submission
5
+ end
@@ -1,4 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Folder < Document
4
- end
3
+ class Folder < Document; end
@@ -1,4 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Group < ActiveRecord::Base
4
- end
3
+ class Group < ActiveRecord::Base; end
@@ -1,4 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Page < Document
4
- end
3
+ class Page < Document; end
@@ -3,4 +3,5 @@
3
3
  class Submission < ActiveRecord::Base
4
4
  belongs_to :user
5
5
  has_many :replies
6
+ has_one :attachment
6
7
  end
@@ -2,5 +2,6 @@
2
2
 
3
3
  class User < ActiveRecord::Base
4
4
  has_one :submission
5
+ has_one :submission_attachment, through: :submission, source: :attachment, class_name: 'Attachment'
5
6
  belongs_to :category
6
7
  end
@@ -1,4 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Writer < BaseUser
4
- end
3
+ class Writer < BaseUser; end
@@ -4,14 +4,16 @@ require 'rspec'
4
4
  begin
5
5
  require 'active_record'
6
6
  rescue LoadError
7
+
7
8
  end
8
9
  begin
9
10
  require 'mongoid'
10
11
  rescue LoadError
12
+
11
13
  end
12
14
 
13
15
  module Rails
14
- class <<self
16
+ class << self
15
17
  def root
16
18
  File.expand_path(__FILE__).split('/')[0..-3].join('/')
17
19
  end
@@ -60,9 +62,7 @@ if active_record?
60
62
  Bullet.enable = true
61
63
  end
62
64
 
63
- config.after(:example) do
64
- Bullet.end_request
65
- end
65
+ config.after(:example) { Bullet.end_request }
66
66
  end
67
67
 
68
68
  if ENV['BULLET_LOG']
@@ -87,13 +87,9 @@ if mongoid?
87
87
  Support::MongoSeed.teardown_db
88
88
  end
89
89
 
90
- config.before(:each) do
91
- Bullet.start_request
92
- end
90
+ config.before(:each) { Bullet.start_request }
93
91
 
94
- config.after(:each) do
95
- Bullet.end_request
96
- end
92
+ config.after(:each) { Bullet.end_request }
97
93
  end
98
94
 
99
95
  if ENV['BULLET_LOG']
@@ -2,9 +2,7 @@
2
2
 
3
3
  module Bullet
4
4
  def self.collected_notifications_of_class(notification_class)
5
- Bullet.notification_collector.collection.select do |notification|
6
- notification.is_a? notification_class
7
- end
5
+ Bullet.notification_collector.collection.select { |notification| notification.is_a? notification_class }
8
6
  end
9
7
 
10
8
  def self.collected_counter_cache_notifications
@@ -23,7 +21,7 @@ end
23
21
  module Bullet
24
22
  module Detector
25
23
  class Association
26
- class <<self
24
+ class << self
27
25
  # returns true if all associations are preloaded
28
26
  def completely_preloading_associations?
29
27
  Bullet.collected_n_plus_one_query_notifications.empty?
@@ -35,21 +33,22 @@ module Bullet
35
33
 
36
34
  # returns true if a given object has a specific association
37
35
  def creating_object_association_for?(object, association)
38
- object_associations[object.bullet_key].present? && object_associations[object.bullet_key].include?(association)
36
+ object_associations[object.bullet_key].present? &&
37
+ object_associations[object.bullet_key].include?(association)
39
38
  end
40
39
 
41
40
  # returns true if a given class includes the specific unpreloaded association
42
41
  def detecting_unpreloaded_association_for?(klass, association)
43
- Bullet.collected_n_plus_one_query_notifications.select { |notification|
42
+ Bullet.collected_n_plus_one_query_notifications.select do |notification|
44
43
  notification.base_class == klass.to_s && notification.associations.include?(association)
45
- }.present?
44
+ end.present?
46
45
  end
47
46
 
48
47
  # returns true if the given class includes the specific unused preloaded association
49
48
  def unused_preload_associations_for?(klass, association)
50
- Bullet.collected_unused_eager_association_notifications.select { |notification|
49
+ Bullet.collected_unused_eager_association_notifications.select do |notification|
51
50
  notification.base_class == klass.to_s && notification.associations.include?(association)
52
- }.present?
51
+ end.present?
53
52
  end
54
53
  end
55
54
  end
@@ -39,25 +39,11 @@ module Support
39
39
  def setup_db
40
40
  if Mongoid::VERSION =~ /\A4/
41
41
  Mongoid.configure do |config|
42
- config.load_configuration(
43
- sessions: {
44
- default: {
45
- database: 'bullet',
46
- hosts: ['localhost:27017']
47
- }
48
- }
49
- )
42
+ config.load_configuration(sessions: { default: { database: 'bullet', hosts: %w[localhost:27017] } })
50
43
  end
51
44
  else
52
45
  Mongoid.configure do |config|
53
- config.load_configuration(
54
- clients: {
55
- default: {
56
- database: 'bullet',
57
- hosts: ['localhost:27017']
58
- }
59
- }
60
- )
46
+ config.load_configuration(clients: { default: { database: 'bullet', hosts: %w[localhost:27017] } })
61
47
  end
62
48
  # Increase the level from DEBUG in order to avoid excessive logging to the screen
63
49
  Mongo::Logger.logger.level = Logger::WARN
@@ -95,6 +95,9 @@ module Support
95
95
  submission1.replies.create(name: 'reply2')
96
96
  submission2.replies.create(name: 'reply3')
97
97
  submission2.replies.create(name: 'reply4')
98
+
99
+ submission1.create_attachment(file_name: 'submission1 file')
100
+ submission2.create_attachment(file_name: 'submission2 file')
98
101
  end
99
102
 
100
103
  def setup_db
@@ -240,6 +243,11 @@ module Support
240
243
  t.column :name, :string
241
244
  t.column :category_id, :integer
242
245
  end
246
+
247
+ create_table :attachments do |t|
248
+ t.column :file_name, :string
249
+ t.column :submission_id, :integer
250
+ end
243
251
  end
244
252
  end
245
253
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.1
4
+ version: 6.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-26 00:00:00.000000000 Z
11
+ date: 2021-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -62,6 +62,7 @@ files:
62
62
  - Gemfile.rails-5.1
63
63
  - Gemfile.rails-5.2
64
64
  - Gemfile.rails-6.0
65
+ - Gemfile.rails-6.1
65
66
  - Guardfile
66
67
  - Hacking.md
67
68
  - MIT-LICENSE
@@ -76,6 +77,7 @@ files:
76
77
  - lib/bullet/active_record5.rb
77
78
  - lib/bullet/active_record52.rb
78
79
  - lib/bullet/active_record60.rb
80
+ - lib/bullet/active_record61.rb
79
81
  - lib/bullet/bullet_xhr.js
80
82
  - lib/bullet/dependency.rb
81
83
  - lib/bullet/detector.rb
@@ -127,6 +129,7 @@ files:
127
129
  - spec/integration/counter_cache_spec.rb
128
130
  - spec/integration/mongoid/association_spec.rb
129
131
  - spec/models/address.rb
132
+ - spec/models/attachment.rb
130
133
  - spec/models/author.rb
131
134
  - spec/models/base_user.rb
132
135
  - spec/models/category.rb
@@ -173,7 +176,7 @@ licenses:
173
176
  metadata:
174
177
  changelog_uri: https://github.com/flyerhzm/bullet/blob/master/CHANGELOG.md
175
178
  source_code_uri: https://github.com/flyerhzm/bullet
176
- post_install_message:
179
+ post_install_message:
177
180
  rdoc_options: []
178
181
  require_paths:
179
182
  - lib
@@ -188,8 +191,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
191
  - !ruby/object:Gem::Version
189
192
  version: 1.3.6
190
193
  requirements: []
191
- rubygems_version: 3.0.3
192
- signing_key:
194
+ rubygems_version: 3.1.4
195
+ signing_key:
193
196
  specification_version: 4
194
197
  summary: help to kill N+1 queries and unused eager loading.
195
198
  test_files:
@@ -214,6 +217,7 @@ test_files:
214
217
  - spec/integration/counter_cache_spec.rb
215
218
  - spec/integration/mongoid/association_spec.rb
216
219
  - spec/models/address.rb
220
+ - spec/models/attachment.rb
217
221
  - spec/models/author.rb
218
222
  - spec/models/base_user.rb
219
223
  - spec/models/category.rb