bullet 7.0.0 → 7.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fbdfd6fe2f412c6632b877352fdf912b56fd54e255101dc16ae414a218fc2ee
4
- data.tar.gz: 0a765e969ccae1ef685051350324052225fea00e80d7d37a6b8cce6d8ad1f28e
3
+ metadata.gz: ad1f81292cc89778a41c6dd178bbfb6342fe1b69c4e57c3fdad0d8003d97b525
4
+ data.tar.gz: 5c1c8113f6e03ecdb449bce5e12273b969f29c323a5bb802c13c0539ea439a69
5
5
  SHA512:
6
- metadata.gz: 35c561cc6534f355a56d1aa0e880bb51941c126ce8a9c704bbc8c0f59c67cf5890a00d650919d5a458a913f4d6a125b17e57c92130d48baa9b6a90db190db763
7
- data.tar.gz: 4f29d4316862401ad1d5d4edfdf21f6f8045a37e21acc4d12f3cdd80e528b12924a9f0a2ab5fdb366432ea5c8e656210887112fc338da8539a34586da88710e9
6
+ metadata.gz: 1f0d4d73910f96ab8c6ae5b6b1bc58de547c2c32a7c689c2984778465dae29d2c2cae81c23699b3848d2eaef30223db66bcca6ccb421b9078d5616f497421d45
7
+ data.tar.gz: 3b9001966918da22bfe7b2960526ac0db471a75e79e7939b099bebe3dde1fb27ea69b1afbdec0fcc98a6cb4260b845b5551a1a07cec036207c885be4e14ef7b9
@@ -76,7 +76,7 @@ jobs:
76
76
  - name: Set up Ruby
77
77
  uses: ruby/setup-ruby@v1
78
78
  with:
79
- ruby-version: 3.0
79
+ ruby-version: 3.1
80
80
  bundler-cache: true
81
81
  - name: Run tests
82
82
  run: bundle exec rake
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  ## Next Release
2
2
 
3
+ ## 7.0.3 (08/13/2022)
4
+
5
+ * Replace `Array()` with `Array.wrap()`
6
+
7
+ ## 7.0.2 (05/31/2022)
8
+
9
+ * Drop growl support
10
+ * Do not check html tag in Bullet::Rack anymore
11
+
12
+ ## 7.0.1 (01/15/2022)
13
+
14
+ * Get rid of *_whitelist methods
15
+ * Hack ActiveRecord::Associations::Preloader::Batch in rails 7
16
+
3
17
  ## 7.0.0 (12/18/2021)
4
18
 
5
19
  * Support rails 7
data/README.md CHANGED
@@ -49,7 +49,7 @@ mongoid.
49
49
 
50
50
  ## Configuration
51
51
 
52
- Bullet won't do ANYTHING unless you tell it to explicitly. Append to
52
+ Bullet won't enable any notification systems unless you tell it to explicitly. Append to
53
53
  `config/environments/development.rb` initializer with the following code:
54
54
 
55
55
  ```ruby
@@ -59,7 +59,6 @@ config.after_initialize do
59
59
  Bullet.alert = true
60
60
  Bullet.bullet_logger = true
61
61
  Bullet.console = true
62
- Bullet.growl = true
63
62
  Bullet.xmpp = { :account => 'bullets_account@jabber.org',
64
63
  :password => 'bullets_password_for_jabber',
65
64
  :receiver => 'your_account@jabber.org',
@@ -85,7 +84,6 @@ The code above will enable all of the Bullet notification systems:
85
84
  * `Bullet.alert`: pop up a JavaScript alert in the browser
86
85
  * `Bullet.bullet_logger`: log to the Bullet log file (Rails.root/log/bullet.log)
87
86
  * `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
88
- * `Bullet.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
89
87
  * `Bullet.xmpp`: send XMPP/Jabber notifications to the receiver indicated. Note that the code will currently not handle the adding of contacts, so you will need to make both accounts indicated know each other manually before you will receive any notifications. If you restart the development server frequently, the 'coming online' sound for the Bullet account may start to annoy - in this case set :show_online_status to false; you will still get notifications, but the Bullet account won't announce it's online status anymore.
90
88
  * `Bullet.rails_logger`: add warnings directly to the Rails log
91
89
  * `Bullet.honeybadger`: add notifications to Honeybadger
@@ -156,25 +154,26 @@ The Bullet log `log/bullet.log` will look something like this:
156
154
  * N+1 Query:
157
155
 
158
156
  ```
159
- 2009-08-25 20:40:17[INFO] N+1 Query: PATH_INFO: /posts; model: Post => associations: [comments]·
160
- Add to your finder: :include => [:comments]
161
- 2009-08-25 20:40:17[INFO] N+1 Query: method call stack:·
162
- /Users/richard/Downloads/test/app/views/posts/index.html.erb:11:in `_run_erb_app47views47posts47index46html46erb'
163
- /Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `each'
164
- /Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `_run_erb_app47views47posts47index46html46erb'
165
- /Users/richard/Downloads/test/app/controllers/posts_controller.rb:7:in `index'
157
+ 2009-08-25 20:40:17[INFO] USE eager loading detected:
158
+ Post => [:comments]·
159
+ Add to your query: .includes([:comments])
160
+ 2009-08-25 20:40:17[INFO] Call stack
161
+ /Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `each'
162
+ /Users/richard/Downloads/test/app/controllers/posts_controller.rb:7:in `index'
166
163
  ```
167
164
 
168
- The first two lines are notifications that N+1 queries have been encountered. The remaining lines are stack traces so you can find exactly where the queries were invoked in your code, and fix them.
165
+ The first log entry is a notification that N+1 queries have been encountered. The remaining entry is a stack trace so you can find exactly where the queries were invoked in your code, and fix them.
169
166
 
170
167
  * Unused eager loading:
171
168
 
172
169
  ```
173
- 2009-08-25 20:53:56[INFO] Unused eager loadings: PATH_INFO: /posts; model: Post => associations: [comments]·
174
- Remove from your finder: :include => [:comments]
170
+ 2009-08-25 20:53:56[INFO] AVOID eager loading detected
171
+ Post => [:comments]·
172
+ Remove from your query: .includes([:comments])
173
+ 2009-08-25 20:53:56[INFO] Call stack
175
174
  ```
176
175
 
177
- These two lines are notifications that unused eager loadings have been encountered.
176
+ These lines are notifications that unused eager loadings have been encountered.
178
177
 
179
178
  * Need counter cache:
180
179
 
@@ -183,10 +182,14 @@ These two lines are notifications that unused eager loadings have been encounter
183
182
  Post => [:comments]
184
183
  ```
185
184
 
186
- ## Growl, XMPP/Jabber and Airbrake Support
185
+ ## XMPP/Jabber and Airbrake Support
187
186
 
188
187
  see [https://github.com/flyerhzm/uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
189
188
 
189
+ ## Growl Support
190
+
191
+ Growl support is dropped from uniform_notifier 1.16.0, if you still want it, please use uniform_notifier 1.15.0.
192
+
190
193
  ## Important
191
194
 
192
195
  If you find Bullet does not work for you, *please disable your browser's cache*.
@@ -270,8 +273,7 @@ Bullet outputs some details info, to enable debug mode, set
270
273
  ## Demo
271
274
 
272
275
  Bullet is designed to function as you browse through your application in development. To see it in action,
273
- you can visit [https://github.com/flyerhzm/bullet_test](https://github.com/flyerhzm/bullet_test) or
274
- follow these steps to create, detect, and fix example query problems.
276
+ you can follow these steps to create, detect, and fix example query problems.
275
277
 
276
278
  1\. Create an example application
277
279
 
@@ -482,4 +484,4 @@ Meanwhile, there's a line appended to `log/bullet.log`
482
484
  Post => [:comments]
483
485
  ```
484
486
 
485
- Copyright (c) 2009 - 2019 Richard Huang (flyerhzm@gmail.com), released under the MIT license
487
+ Copyright (c) 2009 - 2022 Richard Huang (flyerhzm@gmail.com), released under the MIT license
@@ -179,7 +179,7 @@ module Bullet
179
179
  refl = reflection.through_reflection
180
180
  Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
181
181
  association = owner.association refl.name
182
- Array(association.target).each do |through_record|
182
+ Array.wrap(association.target).each do |through_record|
183
183
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
184
184
  end
185
185
 
@@ -152,7 +152,7 @@ module Bullet
152
152
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
153
153
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
154
154
  association = owner.association reflection.through_reflection.name
155
- Array(association.target).each do |through_record|
155
+ Array.wrap(association.target).each do |through_record|
156
156
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
157
157
  end
158
158
 
@@ -199,7 +199,7 @@ module Bullet
199
199
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
200
200
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
201
201
  association = owner.association reflection.through_reflection.name
202
- Array(association.target).each do |through_record|
202
+ Array.wrap(association.target).each do |through_record|
203
203
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
204
204
  end
205
205
 
@@ -179,7 +179,7 @@ module Bullet
179
179
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
180
180
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
181
181
  association = owner.association(reflection.through_reflection.name)
182
- Array(association.target).each do |through_record|
182
+ Array.wrap(association.target).each do |through_record|
183
183
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
184
184
  end
185
185
 
@@ -226,7 +226,7 @@ module Bullet
226
226
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
227
227
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
228
228
  association = owner.association(reflection.through_reflection.name)
229
- Array(association.target).each do |through_record|
229
+ Array.wrap(association.target).each do |through_record|
230
230
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
231
231
  end
232
232
 
@@ -179,7 +179,7 @@ module Bullet
179
179
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
180
180
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
181
181
  association = owner.association(reflection.through_reflection.name)
182
- Array(association.target).each do |through_record|
182
+ Array.wrap(association.target).each do |through_record|
183
183
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
184
184
  end
185
185
 
@@ -226,7 +226,7 @@ module Bullet
226
226
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
227
227
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
228
228
  association = owner.association(reflection.through_reflection.name)
229
- Array(association.target).each do |through_record|
229
+ Array.wrap(association.target).each do |through_record|
230
230
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
231
231
  end
232
232
 
@@ -60,6 +60,20 @@ module Bullet
60
60
  end
61
61
  )
62
62
 
63
+ ::ActiveRecord::Associations::Preloader::Batch.prepend(
64
+ Module.new do
65
+ def call
66
+ if Bullet.start?
67
+ @preloaders.each do |preloader|
68
+ preloader.records.each { |record| Bullet::Detector::Association.add_object_associations(record, preloader.associations) }
69
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
70
+ end
71
+ end
72
+ super
73
+ end
74
+ end
75
+ )
76
+
63
77
  ::ActiveRecord::Associations::Preloader::Branch.prepend(
64
78
  Module.new do
65
79
  def preloaders_for_reflection(reflection, reflection_records)
@@ -168,7 +182,7 @@ module Bullet
168
182
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
169
183
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
170
184
  association = owner.association(reflection.through_reflection.name)
171
- Array(association.target).each do |through_record|
185
+ Array.wrap(association.target).each do |through_record|
172
186
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
173
187
  end
174
188
 
@@ -215,7 +229,7 @@ module Bullet
215
229
  if is_a? ::ActiveRecord::Associations::ThroughAssociation
216
230
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
217
231
  association = owner.association(reflection.through_reflection.name)
218
- Array(association.target).each do |through_record|
232
+ Array.wrap(association.target).each do |through_record|
219
233
  Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
220
234
  end
221
235
 
@@ -20,7 +20,7 @@
20
20
  if (this.onload) {
21
21
  this._storedOnload = this.onload;
22
22
  }
23
- this.onload = null
23
+ this.onload = null;
24
24
  this.addEventListener("load", bulletXHROnload);
25
25
  return Reflect.apply(oldSend, this, arguments);
26
26
  }
@@ -31,7 +31,7 @@
31
31
  ) {
32
32
  var bulletFooterText = this.getResponseHeader("X-bullet-footer-text");
33
33
  if (bulletFooterText) {
34
- setTimeout(function() {
34
+ setTimeout(function () {
35
35
  var oldHtml = document.querySelector("#bullet-footer").innerHTML.split("<br>");
36
36
  var header = oldHtml[0];
37
37
  oldHtml = oldHtml.slice(1, oldHtml.length);
@@ -42,7 +42,7 @@
42
42
  }
43
43
  var bulletConsoleText = this.getResponseHeader("X-bullet-console-text");
44
44
  if (bulletConsoleText && typeof console !== "undefined" && console.log) {
45
- setTimeout(function() {
45
+ setTimeout(function () {
46
46
  JSON.parse(bulletConsoleText).forEach((message) => {
47
47
  if (console.groupCollapsed && console.groupEnd) {
48
48
  console.groupCollapsed("Uniform Notifier");
@@ -20,7 +20,7 @@ module Bullet
20
20
  return unless Bullet.start?
21
21
  return unless Bullet.counter_cache_enable?
22
22
 
23
- objects = Array(object_or_objects)
23
+ objects = Array.wrap(object_or_objects)
24
24
  return if objects.map(&:bullet_primary_key_value).compact.empty?
25
25
 
26
26
  Bullet.debug(
@@ -54,7 +54,7 @@ module Bullet
54
54
  private
55
55
 
56
56
  def create_notification(klazz, associations)
57
- notify_associations = Array(associations) - Bullet.get_safelist_associations(:counter_cache, klazz)
57
+ notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:counter_cache, klazz)
58
58
 
59
59
  if notify_associations.present?
60
60
  notice = Bullet::Notification::CounterCache.new klazz, notify_associations
@@ -7,7 +7,7 @@ module Bullet
7
7
  extend StackTraceFilter
8
8
 
9
9
  class << self
10
- # executed when object.assocations is called.
10
+ # executed when object.associations is called.
11
11
  # first, it keeps this method call for object.association.
12
12
  # then, it checks if this associations call is unpreload.
13
13
  # if it is, keeps this unpreload associations and caller.
@@ -33,7 +33,7 @@ module Bullet
33
33
  return unless Bullet.start?
34
34
  return unless Bullet.n_plus_one_query_enable?
35
35
 
36
- objects = Array(object_or_objects)
36
+ objects = Array.wrap(object_or_objects)
37
37
  return if objects.map(&:bullet_primary_key_value).compact.empty?
38
38
  return if objects.all? { |obj| obj.class.name =~ /^HABTM_/ }
39
39
 
@@ -95,7 +95,7 @@ module Bullet
95
95
  private
96
96
 
97
97
  def create_notification(callers, klazz, associations)
98
- notify_associations = Array(associations) - Bullet.get_safelist_associations(:n_plus_one_query, klazz)
98
+ notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:n_plus_one_query, klazz)
99
99
 
100
100
  if notify_associations.present?
101
101
  notice = Bullet::Notification::NPlusOneQuery.new(callers, klazz, notify_associations)
@@ -10,7 +10,7 @@ module Bullet
10
10
  # check if there are unused preload associations.
11
11
  # get related_objects from eager_loadings associated with object and associations
12
12
  # get call_object_association from associations of call_object_associations whose object is in related_objects
13
- # if association not in call_object_association, then the object => association - call_object_association is ununsed preload assocations
13
+ # if association not in call_object_association, then the object => association - call_object_association is ununsed preload associations
14
14
  def check_unused_preload_associations
15
15
  return unless Bullet.start?
16
16
  return unless Bullet.unused_eager_loading_enable?
@@ -65,7 +65,7 @@ module Bullet
65
65
  private
66
66
 
67
67
  def create_notification(callers, klazz, associations)
68
- notify_associations = Array(associations) - Bullet.get_safelist_associations(:unused_eager_loading, klazz)
68
+ notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:unused_eager_loading, klazz)
69
69
 
70
70
  if notify_associations.present?
71
71
  notice = Bullet::Notification::UnusedEagerLoading.new(callers, klazz, notify_associations)
data/lib/bullet/rack.rb CHANGED
@@ -42,6 +42,7 @@ module Bullet
42
42
  def empty?(response)
43
43
  # response may be ["Not Found"], ["Move Permanently"], etc, but
44
44
  # those should not happen if the status is 200
45
+ return true if !response.respond_to?(:body) && !response.respond_to?(:first)
45
46
  body = response_body(response)
46
47
  body.nil? || body.empty?
47
48
  end
@@ -78,7 +79,7 @@ module Bullet
78
79
  end
79
80
 
80
81
  def html_request?(headers, response)
81
- headers['Content-Type']&.include?('text/html') && response_body(response).include?('<html')
82
+ headers['Content-Type']&.include?('text/html')
82
83
  end
83
84
 
84
85
  def response_body(response)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bullet
4
- VERSION = '7.0.0'
4
+ VERSION = '7.0.3'
5
5
  end
data/lib/bullet.rb CHANGED
@@ -109,7 +109,7 @@ module Bullet
109
109
  end
110
110
 
111
111
  def get_safelist_associations(type, class_name)
112
- Array(@safelist[type][class_name])
112
+ Array.wrap(@safelist[type][class_name])
113
113
  end
114
114
 
115
115
  def reset_safelist
@@ -120,51 +120,6 @@ module Bullet
120
120
  @safelist = nil
121
121
  end
122
122
 
123
- def add_whitelist(options)
124
- ActiveSupport::Deprecation.warn(<<~WARN.strip
125
- add_whitelist is deprecated in favor of add_safelist. It will be removed from the next major release.
126
- WARN
127
- )
128
-
129
- add_safelist(options)
130
- end
131
-
132
- def delete_whitelist(options)
133
- ActiveSupport::Deprecation.warn(<<~WARN.strip
134
- delete_whitelist is deprecated in favor of delete_safelist. It will be removed from the next major release.
135
- WARN
136
- )
137
-
138
- delete_safelist(options)
139
- end
140
-
141
- def get_whitelist_associations(type, class_name)
142
- ActiveSupport::Deprecation.warn(<<~WARN.strip
143
- get_whitelist_associations is deprecated in favor of get_safelist_associations. It will be removed from the next major release.
144
- WARN
145
- )
146
-
147
- get_safelist_associations(type, class_name)
148
- end
149
-
150
- def reset_whitelist
151
- ActiveSupport::Deprecation.warn(<<~WARN.strip
152
- reset_whitelist is deprecated in favor of reset_safelist. It will be removed from the next major release.
153
- WARN
154
- )
155
-
156
- reset_safelist
157
- end
158
-
159
- def clear_whitelist
160
- ActiveSupport::Deprecation.warn(<<~WARN.strip
161
- clear_whitelist is deprecated in favor of clear_safelist. It will be removed from the next major release.
162
- WARN
163
- )
164
-
165
- clear_safelist
166
- end
167
-
168
123
  def bullet_logger=(active)
169
124
  if active
170
125
  require 'fileutils'
@@ -16,7 +16,6 @@ module Bullet
16
16
  Bullet.alert = true
17
17
  Bullet.bullet_logger = true
18
18
  Bullet.console = true
19
- # Bullet.growl = true
20
19
  Bullet.rails_logger = true
21
20
  Bullet.add_footer = true
22
21
  end
@@ -39,7 +39,7 @@ module Bullet
39
39
 
40
40
  it 'should be false if object, association pair is not existed' do
41
41
  NPlusOneQuery.add_object_associations(@post, :association1)
42
- expect(NPlusOneQuery.association?(@post, :associatio2)).to eq false
42
+ expect(NPlusOneQuery.association?(@post, :association2)).to eq false
43
43
  end
44
44
  end
45
45
 
@@ -74,8 +74,8 @@ module Bullet
74
74
  it 'should send full_notice to notifier' do
75
75
  notifier = double
76
76
  allow(subject).to receive(:notifier).and_return(notifier)
77
- allow(subject).to receive(:notification_data).and_return(foo: :bar)
78
- expect(notifier).to receive(:inline_notify).with(foo: :bar)
77
+ allow(subject).to receive(:notification_data).and_return({ foo: :bar })
78
+ expect(notifier).to receive(:inline_notify).with({ foo: :bar })
79
79
  subject.notify_inline
80
80
  end
81
81
  end
@@ -84,8 +84,8 @@ module Bullet
84
84
  it 'should send full_out_of_channel to notifier' do
85
85
  notifier = double
86
86
  allow(subject).to receive(:notifier).and_return(notifier)
87
- allow(subject).to receive(:notification_data).and_return(foo: :bar)
88
- expect(notifier).to receive(:out_of_channel_notify).with(foo: :bar)
87
+ allow(subject).to receive(:notification_data).and_return({ foo: :bar })
88
+ expect(notifier).to receive(:out_of_channel_notify).with({ foo: :bar })
89
89
  subject.notify_out_of_channel
90
90
  end
91
91
  end
@@ -31,12 +31,6 @@ module Bullet
31
31
  response = double(body: '<html><head></head><body></body></html>')
32
32
  expect(middleware).not_to be_html_request(headers, response)
33
33
  end
34
-
35
- it "should be false if response body doesn't contain html tag" do
36
- headers = { 'Content-Type' => 'text/html' }
37
- response = double(body: '<div>Partial</div>')
38
- expect(middleware).not_to be_html_request(headers, response)
39
- end
40
34
  end
41
35
 
42
36
  context 'empty?' do
@@ -54,6 +48,11 @@ module Bullet
54
48
  response = double(body: '')
55
49
  expect(middleware).to be_empty(response)
56
50
  end
51
+
52
+ it 'should be true if no response body' do
53
+ response = double()
54
+ expect(middleware).to be_empty(response)
55
+ end
57
56
  end
58
57
 
59
58
  context '#call' do
data/spec/bullet_spec.rb CHANGED
@@ -83,15 +83,6 @@ describe Bullet, focused: true do
83
83
  end
84
84
  end
85
85
 
86
- describe '#add_whitelist' do
87
- context "for 'special' class names" do
88
- it 'is added to the safelist successfully' do
89
- Bullet.add_whitelist(type: :n_plus_one_query, class_name: 'Klass', association: :department)
90
- expect(Bullet.get_safelist_associations(:n_plus_one_query, 'Klass')).to include :department
91
- end
92
- end
93
- end
94
-
95
86
  describe '#delete_safelist' do
96
87
  context "for 'special' class names" do
97
88
  it 'is deleted from the safelist successfully' do
@@ -112,26 +103,6 @@ describe Bullet, focused: true do
112
103
  end
113
104
  end
114
105
 
115
- describe '#delete_whitelist' do
116
- context "for 'special' class names" do
117
- it 'is deleted from the safelist successfully' do
118
- Bullet.add_safelist(type: :n_plus_one_query, class_name: 'Klass', association: :department)
119
- Bullet.delete_whitelist(type: :n_plus_one_query, class_name: 'Klass', association: :department)
120
- expect(Bullet.safelist[:n_plus_one_query]).to eq({})
121
- end
122
- end
123
-
124
- context 'when exists multiple definitions' do
125
- it 'is deleted from the safelist successfully' do
126
- Bullet.add_safelist(type: :n_plus_one_query, class_name: 'Klass', association: :department)
127
- Bullet.add_safelist(type: :n_plus_one_query, class_name: 'Klass', association: :team)
128
- Bullet.delete_whitelist(type: :n_plus_one_query, class_name: 'Klass', association: :team)
129
- expect(Bullet.get_safelist_associations(:n_plus_one_query, 'Klass')).to include :department
130
- expect(Bullet.get_safelist_associations(:n_plus_one_query, 'Klass')).to_not include :team
131
- end
132
- end
133
- end
134
-
135
106
  describe '#perform_out_of_channel_notifications' do
136
107
  let(:notification) { double }
137
108
 
@@ -451,6 +451,16 @@ if active_record?
451
451
  expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Student, :teachers)
452
452
  end
453
453
  end
454
+
455
+ context 'user => roles' do
456
+ it 'should detect preload associations' do
457
+ User.first.roles.includes(:resource).each { |role| role.resource }
458
+ Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
459
+ expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
460
+
461
+ expect(Bullet::Detector::Association).to be_completely_preloading_associations
462
+ end
463
+ end
454
464
  end
455
465
 
456
466
  describe Bullet::Detector::Association, 'has_many :through' do
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Role < ActiveRecord::Base
4
+ has_and_belongs_to_many :users
5
+
6
+ belongs_to :resource, polymorphic: true
7
+ end
data/spec/models/user.rb CHANGED
@@ -4,4 +4,5 @@ class User < ActiveRecord::Base
4
4
  has_one :submission
5
5
  has_one :submission_attachment, through: :submission, source: :attachment, class_name: 'Attachment'
6
6
  belongs_to :category
7
+ has_and_belongs_to_many :roles
7
8
  end
@@ -92,9 +92,16 @@ module Support
92
92
  page3 = Page.create(name: 'page3', parent_id: folder2.id, author_id: author2.id)
93
93
  page4 = Page.create(name: 'page4', parent_id: folder2.id, author_id: author2.id)
94
94
 
95
+ role1 = Role.create(name: 'Admin')
96
+ role2 = Role.create(name: 'User')
97
+
95
98
  user1 = User.create(name: 'user1', category: category1)
96
99
  user2 = User.create(name: 'user2', category: category1)
97
100
 
101
+ user1.roles << role1
102
+ user1.roles << role2
103
+ user2.roles << role2
104
+
98
105
  submission1 = user1.create_submission(name: 'submission1')
99
106
  submission2 = user2.create_submission(name: 'submission2')
100
107
 
@@ -246,6 +253,17 @@ module Support
246
253
  t.column :submission_id, :integer
247
254
  end
248
255
 
256
+ create_table :roles do |t|
257
+ t.column :name, :string
258
+ t.column :resource_id, :integer
259
+ t.column :resource_type, :string
260
+ end
261
+
262
+ create_table :roles_users do |t|
263
+ t.column :role_id, :integer
264
+ t.column :user_id, :integer
265
+ end
266
+
249
267
  create_table :submissions do |t|
250
268
  t.column :name, :string
251
269
  t.column :user_id, :integer
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: 7.0.0
4
+ version: 7.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-18 00:00:00.000000000 Z
11
+ date: 2022-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -160,6 +160,7 @@ files:
160
160
  - spec/models/post.rb
161
161
  - spec/models/relationship.rb
162
162
  - spec/models/reply.rb
163
+ - spec/models/role.rb
163
164
  - spec/models/student.rb
164
165
  - spec/models/submission.rb
165
166
  - spec/models/teacher.rb
@@ -194,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
195
  - !ruby/object:Gem::Version
195
196
  version: 1.3.6
196
197
  requirements: []
197
- rubygems_version: 3.2.22
198
+ rubygems_version: 3.3.7
198
199
  signing_key:
199
200
  specification_version: 4
200
201
  summary: help to kill N+1 queries and unused eager loading.
@@ -249,6 +250,7 @@ test_files:
249
250
  - spec/models/post.rb
250
251
  - spec/models/relationship.rb
251
252
  - spec/models/reply.rb
253
+ - spec/models/role.rb
252
254
  - spec/models/student.rb
253
255
  - spec/models/submission.rb
254
256
  - spec/models/teacher.rb