bullet 6.1.0 → 7.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +82 -0
  3. data/CHANGELOG.md +31 -0
  4. data/Gemfile.rails-6.0 +1 -1
  5. data/Gemfile.rails-6.1 +15 -0
  6. data/Gemfile.rails-7.0 +10 -0
  7. data/README.md +17 -7
  8. data/lib/bullet/active_job.rb +5 -1
  9. data/lib/bullet/active_record41.rb +1 -0
  10. data/lib/bullet/active_record42.rb +1 -0
  11. data/lib/bullet/active_record52.rb +22 -17
  12. data/lib/bullet/active_record60.rb +22 -17
  13. data/lib/bullet/active_record61.rb +272 -0
  14. data/lib/bullet/active_record70.rb +261 -0
  15. data/lib/bullet/bullet_xhr.js +18 -17
  16. data/lib/bullet/dependency.rb +16 -0
  17. data/lib/bullet/detector/base.rb +2 -1
  18. data/lib/bullet/detector/counter_cache.rb +1 -1
  19. data/lib/bullet/detector/n_plus_one_query.rb +3 -3
  20. data/lib/bullet/detector/unused_eager_loading.rb +1 -1
  21. data/lib/bullet/mongoid4x.rb +1 -1
  22. data/lib/bullet/mongoid5x.rb +1 -1
  23. data/lib/bullet/mongoid6x.rb +1 -1
  24. data/lib/bullet/mongoid7x.rb +24 -7
  25. data/lib/bullet/notification.rb +2 -1
  26. data/lib/bullet/rack.rb +26 -18
  27. data/lib/bullet/stack_trace_filter.rb +7 -9
  28. data/lib/bullet/version.rb +1 -1
  29. data/lib/bullet.rb +69 -23
  30. data/lib/generators/bullet/install_generator.rb +23 -25
  31. data/perf/benchmark.rb +4 -1
  32. data/spec/bullet/detector/counter_cache_spec.rb +1 -1
  33. data/spec/bullet/detector/unused_eager_loading_spec.rb +10 -10
  34. data/spec/bullet/ext/object_spec.rb +1 -1
  35. data/spec/bullet/notification/n_plus_one_query_spec.rb +1 -3
  36. data/spec/bullet/rack_spec.rb +130 -3
  37. data/spec/bullet_spec.rb +39 -10
  38. data/spec/integration/active_record/association_spec.rb +54 -10
  39. data/spec/integration/counter_cache_spec.rb +4 -4
  40. data/spec/integration/mongoid/association_spec.rb +4 -4
  41. data/spec/models/attachment.rb +5 -0
  42. data/spec/models/deal.rb +5 -0
  43. data/spec/models/folder.rb +2 -1
  44. data/spec/models/group.rb +2 -1
  45. data/spec/models/page.rb +2 -1
  46. data/spec/models/post.rb +2 -0
  47. data/spec/models/submission.rb +1 -0
  48. data/spec/models/user.rb +1 -0
  49. data/spec/models/writer.rb +2 -1
  50. data/spec/spec_helper.rb +0 -2
  51. data/spec/support/mongo_seed.rb +1 -0
  52. data/spec/support/sqlite_seed.rb +20 -0
  53. data/test.sh +2 -0
  54. metadata +15 -7
  55. data/.travis.yml +0 -33
@@ -129,7 +129,7 @@ if active_record?
129
129
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
130
130
  end
131
131
 
132
- it 'should detect unused preload with post => commnets, no category => posts' do
132
+ it 'should detect unused preload with post => comments, no category => posts' do
133
133
  Category.includes(posts: :comments).each { |category| category.posts.map(&:name) }
134
134
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
135
135
  expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
@@ -202,7 +202,7 @@ if active_record?
202
202
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
203
203
  end
204
204
 
205
- it 'should detect preload with post => commnets' do
205
+ it 'should detect preload with post => comments' do
206
206
  Post.first.comments.map(&:name)
207
207
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
208
208
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
@@ -377,8 +377,7 @@ if active_record?
377
377
  it 'should detect unused preload with comment => author' do
378
378
  Comment.includes([:author, { post: :writer }]).where(['base_users.id = ?', BaseUser.first]).references(
379
379
  :base_users
380
- )
381
- .each { |comment| comment.post.writer.name }
380
+ ).each { |comment| comment.post.writer.name }
382
381
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
383
382
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
384
383
 
@@ -402,6 +401,15 @@ if active_record?
402
401
  end
403
402
 
404
403
  describe Bullet::Detector::Association, 'has_and_belongs_to_many' do
404
+ context 'posts <=> deals' do
405
+ it 'should detect preload associations with join tables that have identifier' do
406
+ Post.includes(:deals).each { |post| post.deals.map(&:name) }
407
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
408
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
409
+
410
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
411
+ end
412
+ end
405
413
  context 'students <=> teachers' do
406
414
  it 'should detect non preload associations' do
407
415
  Student.all.each { |student| student.teachers.map(&:name) }
@@ -562,6 +570,42 @@ if active_record?
562
570
  end
563
571
  end
564
572
 
573
+ describe Bullet::Detector::Association, 'has_one :through' do
574
+ context 'user => attachment' do
575
+ it 'should detect non preload associations' do
576
+ User.all.each { |user| user.submission_attachment.file_name }
577
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
578
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
579
+
580
+ expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(User, :submission_attachment)
581
+ end
582
+
583
+ it 'should detect preload associations' do
584
+ User.includes(:submission_attachment).each { |user| user.submission_attachment.file_name }
585
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
586
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
587
+
588
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
589
+ end
590
+
591
+ it 'should not detect preload associations' do
592
+ User.all.map(&:name)
593
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
594
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
595
+
596
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
597
+ end
598
+
599
+ it 'should detect unused preload associations' do
600
+ User.includes(:submission_attachment).map(&:name)
601
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
602
+ expect(Bullet::Detector::Association).to be_unused_preload_associations_for(User, :submission_attachment)
603
+
604
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
605
+ end
606
+ end
607
+ end
608
+
565
609
  describe Bullet::Detector::Association, 'call one association that in possible objects' do
566
610
  it 'should not detect preload association' do
567
611
  Post.all
@@ -694,9 +738,9 @@ if active_record?
694
738
  end
695
739
  end
696
740
 
697
- context 'whitelist n plus one query' do
698
- before { Bullet.add_whitelist type: :n_plus_one_query, class_name: 'Post', association: :comments }
699
- after { Bullet.clear_whitelist }
741
+ context 'add n plus one query to safelist' do
742
+ before { Bullet.add_safelist type: :n_plus_one_query, class_name: 'Post', association: :comments }
743
+ after { Bullet.clear_safelist }
700
744
 
701
745
  it 'should not detect n plus one query' do
702
746
  Post.all.each { |post| post.comments.map(&:name) }
@@ -715,9 +759,9 @@ if active_record?
715
759
  end
716
760
  end
717
761
 
718
- context 'whitelist unused eager loading' do
719
- before { Bullet.add_whitelist type: :unused_eager_loading, class_name: 'Post', association: :comments }
720
- after { Bullet.clear_whitelist }
762
+ context 'add unused eager loading to safelist' do
763
+ before { Bullet.add_safelist type: :unused_eager_loading, class_name: 'Post', association: :comments }
764
+ after { Bullet.clear_safelist }
721
765
 
722
766
  it 'should not detect unused eager loading' do
723
767
  Post.includes(:comments).map(&:name)
@@ -28,7 +28,7 @@ if !mongoid? && active_record?
28
28
  expect(Bullet.collected_counter_cache_notifications).to be_empty
29
29
  end
30
30
 
31
- if active_record5? || active_record6?
31
+ if ActiveRecord::VERSION::MAJOR > 4
32
32
  it 'should not need counter cache for has_many through' do
33
33
  Client.all.each { |client| client.firms.size }
34
34
  expect(Bullet.collected_counter_cache_notifications).to be_empty
@@ -55,9 +55,9 @@ if !mongoid? && active_record?
55
55
  end
56
56
  end
57
57
 
58
- context 'whitelist' do
59
- before { Bullet.add_whitelist type: :counter_cache, class_name: 'Country', association: :cities }
60
- after { Bullet.clear_whitelist }
58
+ context 'safelist' do
59
+ before { Bullet.add_safelist type: :counter_cache, class_name: 'Country', association: :cities }
60
+ after { Bullet.clear_safelist }
61
61
 
62
62
  it 'should not detect counter cache' do
63
63
  Country.all.each { |country| country.cities.size }
@@ -73,9 +73,9 @@ if mongoid?
73
73
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
74
74
 
75
75
  expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(
76
- Mongoid::Category,
77
- :posts
78
- )
76
+ Mongoid::Category,
77
+ :posts
78
+ )
79
79
  expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Mongoid::Category, :entries)
80
80
  end
81
81
 
@@ -118,7 +118,7 @@ if mongoid?
118
118
  expect(Bullet::Detector::Association).to be_completely_preloading_associations
119
119
  end
120
120
 
121
- it 'should detect preload with post => commnets' do
121
+ it 'should detect preload with post => comments' do
122
122
  Mongoid::Post.first.comments.map(&:name)
123
123
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
124
124
  expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Attachment < ActiveRecord::Base
4
+ belongs_to :submission
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Deal < ActiveRecord::Base
4
+ has_and_belongs_to_many :posts
5
+ end
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Folder < Document; end
3
+ class Folder < Document
4
+ end
data/spec/models/group.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Group < ActiveRecord::Base; end
3
+ class Group < ActiveRecord::Base
4
+ end
data/spec/models/page.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Page < Document; end
3
+ class Page < Document
4
+ end
data/spec/models/post.rb CHANGED
@@ -4,6 +4,7 @@ class Post < ActiveRecord::Base
4
4
  belongs_to :category, inverse_of: :posts
5
5
  belongs_to :writer
6
6
  has_many :comments, inverse_of: :post
7
+ has_and_belongs_to_many :deals
7
8
 
8
9
  validates :category, presence: true
9
10
 
@@ -21,6 +22,7 @@ class Post < ActiveRecord::Base
21
22
  next unless trigger_after_save
22
23
 
23
24
  temp_comment = Comment.new(post: self)
25
+
24
26
  # this triggers self to be "possible", even though it's
25
27
  # not saved yet
26
28
  temp_comment.post
@@ -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
data/spec/models/user.rb CHANGED
@@ -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,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Writer < BaseUser; end
3
+ class Writer < BaseUser
4
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,12 +4,10 @@ require 'rspec'
4
4
  begin
5
5
  require 'active_record'
6
6
  rescue LoadError
7
-
8
7
  end
9
8
  begin
10
9
  require 'mongoid'
11
10
  rescue LoadError
12
-
13
11
  end
14
12
 
15
13
  module Rails
@@ -45,6 +45,7 @@ module Support
45
45
  Mongoid.configure do |config|
46
46
  config.load_configuration(clients: { default: { database: 'bullet', hosts: %w[localhost:27017] } })
47
47
  end
48
+
48
49
  # Increase the level from DEBUG in order to avoid excessive logging to the screen
49
50
  Mongo::Logger.logger.level = Logger::WARN
50
51
  end
@@ -21,6 +21,13 @@ module Support
21
21
  post2 = category2.posts.create(name: 'second', writer: writer2)
22
22
  post3 = category2.posts.create(name: 'third', writer: writer2)
23
23
 
24
+ deal1 = Deal.new(name: 'Deal 1')
25
+ deal1.posts << post1
26
+ deal1.posts << post2
27
+ deal2 = Deal.new(name: 'Deal 2')
28
+ post1.deals << deal1
29
+ post1.deals << deal2
30
+
24
31
  comment1 = post1.comments.create(name: 'first', author: writer1)
25
32
  comment2 = post1.comments.create(name: 'first2', author: writer1)
26
33
  comment3 = post1.comments.create(name: 'first3', author: writer1)
@@ -95,6 +102,9 @@ module Support
95
102
  submission1.replies.create(name: 'reply2')
96
103
  submission2.replies.create(name: 'reply3')
97
104
  submission2.replies.create(name: 'reply4')
105
+
106
+ submission1.create_attachment(file_name: 'submission1 file')
107
+ submission2.create_attachment(file_name: 'submission2 file')
98
108
  end
99
109
 
100
110
  def setup_db
@@ -153,6 +163,11 @@ module Support
153
163
  t.column :hotel_id, :integer
154
164
  end
155
165
 
166
+ create_table :deals_posts do |t|
167
+ t.column :deal_id, :integer
168
+ t.column :post_id, :integer
169
+ end
170
+
156
171
  create_table :documents do |t|
157
172
  t.string :name
158
173
  t.string :type
@@ -240,6 +255,11 @@ module Support
240
255
  t.column :name, :string
241
256
  t.column :category_id, :integer
242
257
  end
258
+
259
+ create_table :attachments do |t|
260
+ t.column :file_name, :string
261
+ t.column :submission_id, :integer
262
+ end
243
263
  end
244
264
  end
245
265
  end
data/test.sh CHANGED
@@ -1,5 +1,7 @@
1
1
  #bundle update rails && bundle exec rspec spec
2
2
  #BUNDLE_GEMFILE=Gemfile.mongoid bundle update mongoid && BUNDLE_GEMFILE=Gemfile.mongoid bundle exec rspec spec
3
+ BUNDLE_GEMFILE=Gemfile.rails-7.0 bundle && BUNDLE_GEMFILE=Gemfile.rails-7.0 bundle exec rspec spec
4
+ BUNDLE_GEMFILE=Gemfile.rails-6.1 bundle && BUNDLE_GEMFILE=Gemfile.rails-6.1 bundle exec rspec spec
3
5
  BUNDLE_GEMFILE=Gemfile.rails-6.0 bundle && BUNDLE_GEMFILE=Gemfile.rails-6.0 bundle exec rspec spec
4
6
  BUNDLE_GEMFILE=Gemfile.rails-5.2 bundle && BUNDLE_GEMFILE=Gemfile.rails-5.2 bundle exec rspec spec
5
7
  BUNDLE_GEMFILE=Gemfile.rails-5.1 bundle && BUNDLE_GEMFILE=Gemfile.rails-5.1 bundle exec rspec spec
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.1.0
4
+ version: 7.0.0
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-12-28 00:00:00.000000000 Z
11
+ date: 2021-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -45,9 +45,9 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - ".github/workflows/main.yml"
48
49
  - ".gitignore"
49
50
  - ".rspec"
50
- - ".travis.yml"
51
51
  - CHANGELOG.md
52
52
  - Gemfile
53
53
  - Gemfile.mongoid
@@ -62,6 +62,8 @@ files:
62
62
  - Gemfile.rails-5.1
63
63
  - Gemfile.rails-5.2
64
64
  - Gemfile.rails-6.0
65
+ - Gemfile.rails-6.1
66
+ - Gemfile.rails-7.0
65
67
  - Guardfile
66
68
  - Hacking.md
67
69
  - MIT-LICENSE
@@ -76,6 +78,8 @@ files:
76
78
  - lib/bullet/active_record5.rb
77
79
  - lib/bullet/active_record52.rb
78
80
  - lib/bullet/active_record60.rb
81
+ - lib/bullet/active_record61.rb
82
+ - lib/bullet/active_record70.rb
79
83
  - lib/bullet/bullet_xhr.js
80
84
  - lib/bullet/dependency.rb
81
85
  - lib/bullet/detector.rb
@@ -127,6 +131,7 @@ files:
127
131
  - spec/integration/counter_cache_spec.rb
128
132
  - spec/integration/mongoid/association_spec.rb
129
133
  - spec/models/address.rb
134
+ - spec/models/attachment.rb
130
135
  - spec/models/author.rb
131
136
  - spec/models/base_user.rb
132
137
  - spec/models/category.rb
@@ -135,6 +140,7 @@ files:
135
140
  - spec/models/comment.rb
136
141
  - spec/models/company.rb
137
142
  - spec/models/country.rb
143
+ - spec/models/deal.rb
138
144
  - spec/models/document.rb
139
145
  - spec/models/entry.rb
140
146
  - spec/models/firm.rb
@@ -173,7 +179,7 @@ licenses:
173
179
  metadata:
174
180
  changelog_uri: https://github.com/flyerhzm/bullet/blob/master/CHANGELOG.md
175
181
  source_code_uri: https://github.com/flyerhzm/bullet
176
- post_install_message:
182
+ post_install_message:
177
183
  rdoc_options: []
178
184
  require_paths:
179
185
  - lib
@@ -188,8 +194,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
194
  - !ruby/object:Gem::Version
189
195
  version: 1.3.6
190
196
  requirements: []
191
- rubygems_version: 3.0.3
192
- signing_key:
197
+ rubygems_version: 3.2.22
198
+ signing_key:
193
199
  specification_version: 4
194
200
  summary: help to kill N+1 queries and unused eager loading.
195
201
  test_files:
@@ -214,6 +220,7 @@ test_files:
214
220
  - spec/integration/counter_cache_spec.rb
215
221
  - spec/integration/mongoid/association_spec.rb
216
222
  - spec/models/address.rb
223
+ - spec/models/attachment.rb
217
224
  - spec/models/author.rb
218
225
  - spec/models/base_user.rb
219
226
  - spec/models/category.rb
@@ -222,6 +229,7 @@ test_files:
222
229
  - spec/models/comment.rb
223
230
  - spec/models/company.rb
224
231
  - spec/models/country.rb
232
+ - spec/models/deal.rb
225
233
  - spec/models/document.rb
226
234
  - spec/models/entry.rb
227
235
  - spec/models/firm.rb
data/.travis.yml DELETED
@@ -1,33 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.3.0
4
- - 2.6.0
5
- gemfile:
6
- - Gemfile.rails-6.0
7
- - Gemfile.rails-5.2
8
- - Gemfile.rails-5.1
9
- - Gemfile.rails-5.0
10
- - Gemfile.rails-4.2
11
- - Gemfile.rails-4.1
12
- - Gemfile.rails-4.0
13
- matrix:
14
- exclude:
15
- - rvm: 2.3.0
16
- gemfile: Gemfile.rails-6.0
17
- - rvm: 2.6.0
18
- gemfile: Gemfile.rails-5.2
19
- - rvm: 2.6.0
20
- gemfile: Gemfile.rails-5.1
21
- - rvm: 2.6.0
22
- gemfile: Gemfile.rails-5.0
23
- - rvm: 2.6.0
24
- gemfile: Gemfile.rails-4.2
25
- - rvm: 2.6.0
26
- gemfile: Gemfile.rails-4.1
27
- - rvm: 2.6.0
28
- gemfile: Gemfile.rails-4.0
29
- env:
30
- - DB=sqlite
31
- before_install:
32
- - "find /home/travis/.rvm/rubies -wholename '*default/bundler-*.gemspec' -delete"
33
- - gem install bundler -v '< 2'