bullet 6.0.2 → 6.1.4
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/CHANGELOG.md +25 -0
- data/Gemfile.rails-6.0 +1 -1
- data/Gemfile.rails-6.1 +15 -0
- data/README.md +12 -2
- data/lib/bullet.rb +31 -20
- data/lib/bullet/active_job.rb +1 -3
- data/lib/bullet/active_record4.rb +9 -23
- data/lib/bullet/active_record41.rb +7 -19
- data/lib/bullet/active_record42.rb +8 -16
- data/lib/bullet/active_record5.rb +188 -170
- data/lib/bullet/active_record52.rb +187 -161
- data/lib/bullet/active_record60.rb +194 -175
- data/lib/bullet/active_record61.rb +278 -0
- data/lib/bullet/bullet_xhr.js +17 -23
- data/lib/bullet/dependency.rb +42 -34
- data/lib/bullet/detector/association.rb +24 -18
- data/lib/bullet/detector/base.rb +1 -2
- data/lib/bullet/detector/counter_cache.rb +10 -6
- data/lib/bullet/detector/n_plus_one_query.rb +18 -8
- data/lib/bullet/detector/unused_eager_loading.rb +5 -2
- data/lib/bullet/mongoid4x.rb +3 -7
- data/lib/bullet/mongoid5x.rb +3 -7
- data/lib/bullet/mongoid6x.rb +3 -7
- data/lib/bullet/mongoid7x.rb +3 -7
- data/lib/bullet/notification/base.rb +14 -18
- data/lib/bullet/notification/n_plus_one_query.rb +2 -4
- data/lib/bullet/notification/unused_eager_loading.rb +2 -4
- data/lib/bullet/rack.rb +23 -15
- data/lib/bullet/stack_trace_filter.rb +7 -16
- data/lib/bullet/version.rb +1 -1
- data/lib/generators/bullet/install_generator.rb +23 -23
- data/perf/benchmark.rb +8 -14
- data/spec/bullet/detector/counter_cache_spec.rb +6 -6
- data/spec/bullet/detector/n_plus_one_query_spec.rb +7 -3
- data/spec/bullet/detector/unused_eager_loading_spec.rb +19 -6
- data/spec/bullet/notification/base_spec.rb +1 -3
- data/spec/bullet/notification/n_plus_one_query_spec.rb +16 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +5 -1
- data/spec/bullet/rack_spec.rb +133 -7
- data/spec/bullet/registry/association_spec.rb +2 -2
- data/spec/bullet/registry/base_spec.rb +1 -1
- data/spec/bullet_spec.rb +10 -29
- data/spec/integration/active_record/association_spec.rb +77 -122
- data/spec/integration/counter_cache_spec.rb +10 -30
- data/spec/integration/mongoid/association_spec.rb +18 -32
- data/spec/models/attachment.rb +5 -0
- data/spec/models/folder.rb +1 -2
- data/spec/models/group.rb +1 -2
- data/spec/models/page.rb +1 -2
- data/spec/models/submission.rb +1 -0
- data/spec/models/user.rb +1 -0
- data/spec/models/writer.rb +1 -2
- data/spec/spec_helper.rb +6 -10
- data/spec/support/bullet_ext.rb +8 -9
- data/spec/support/mongo_seed.rb +2 -16
- data/spec/support/sqlite_seed.rb +8 -0
- metadata +10 -6
@@ -26,9 +26,7 @@ module Bullet
|
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'should leverage ENV parameter' do
|
29
|
-
temp_env_variable('USER', 'bogus')
|
30
|
-
expect(subject.whoami).to eq('user: bogus')
|
31
|
-
end
|
29
|
+
temp_env_variable('USER', 'bogus') { expect(subject.whoami).to eq('user: bogus') }
|
32
30
|
end
|
33
31
|
|
34
32
|
it 'should return blank if no user available' do
|
@@ -7,9 +7,22 @@ module Bullet
|
|
7
7
|
describe NPlusOneQuery do
|
8
8
|
subject { NPlusOneQuery.new([%w[caller1 caller2]], Post, %i[comments votes], 'path') }
|
9
9
|
|
10
|
-
it
|
11
|
-
|
12
|
-
|
10
|
+
it do
|
11
|
+
expect(subject.body_with_caller).to eq(
|
12
|
+
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n"
|
13
|
+
)
|
14
|
+
end
|
15
|
+
it do
|
16
|
+
expect([subject.body_with_caller, subject.body_with_caller]).to eq(
|
17
|
+
[
|
18
|
+
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n",
|
19
|
+
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n"
|
20
|
+
]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
it do
|
24
|
+
expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])")
|
25
|
+
end
|
13
26
|
it { expect(subject.title).to eq('USE eager loading in path') }
|
14
27
|
end
|
15
28
|
end
|
@@ -7,7 +7,11 @@ module Bullet
|
|
7
7
|
describe UnusedEagerLoading do
|
8
8
|
subject { UnusedEagerLoading.new([''], Post, %i[comments votes], 'path') }
|
9
9
|
|
10
|
-
it
|
10
|
+
it do
|
11
|
+
expect(subject.body).to eq(
|
12
|
+
" Post => [:comments, :votes]\n Remove from your query: .includes([:comments, :votes])"
|
13
|
+
)
|
14
|
+
end
|
11
15
|
it { expect(subject.title).to eq('AVOID eager loading in path') }
|
12
16
|
end
|
13
17
|
end
|
data/spec/bullet/rack_spec.rb
CHANGED
@@ -67,12 +67,12 @@ module Bullet
|
|
67
67
|
|
68
68
|
it 'should change response body if notification is active' do
|
69
69
|
expect(Bullet).to receive(:notification?).and_return(true)
|
70
|
+
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
70
71
|
expect(Bullet).to receive(:gather_inline_notifications).and_return('<bullet></bullet>')
|
71
|
-
expect(middleware).to receive(:xhr_script).and_return('')
|
72
72
|
expect(Bullet).to receive(:perform_out_of_channel_notifications)
|
73
|
-
|
73
|
+
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
74
74
|
expect(headers['Content-Length']).to eq('56')
|
75
|
-
expect(response).to eq([
|
75
|
+
expect(response).to eq(%w[<html><head></head><body><bullet></bullet></body></html>])
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'should set the right Content-Length if response body contains accents' do
|
@@ -80,9 +80,135 @@ module Bullet
|
|
80
80
|
response.body = '<html><head></head><body>é</body></html>'
|
81
81
|
app.response = response
|
82
82
|
expect(Bullet).to receive(:notification?).and_return(true)
|
83
|
+
allow(Bullet).to receive(:console_enabled?).and_return(true)
|
83
84
|
expect(Bullet).to receive(:gather_inline_notifications).and_return('<bullet></bullet>')
|
84
|
-
|
85
|
-
expect(headers['Content-Length']).to eq(
|
85
|
+
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
86
|
+
expect(headers['Content-Length']).to eq('58')
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'with injection notifiers' do
|
90
|
+
before do
|
91
|
+
expect(Bullet).to receive(:notification?).and_return(true)
|
92
|
+
allow(Bullet).to receive(:gather_inline_notifications).and_return('<bullet></bullet>')
|
93
|
+
allow(middleware).to receive(:xhr_script).and_return('<script></script>')
|
94
|
+
allow(middleware).to receive(:footer_note).and_return('footer')
|
95
|
+
expect(Bullet).to receive(:perform_out_of_channel_notifications)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should change response body if add_footer is true' do
|
99
|
+
expect(Bullet).to receive(:add_footer).exactly(3).times.and_return(true)
|
100
|
+
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
101
|
+
|
102
|
+
expect(headers['Content-Length']).to eq((73 + middleware.send(:footer_note).length).to_s)
|
103
|
+
expect(response).to eq(%w[<html><head></head><body>footer<bullet></bullet><script></script></body></html>])
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should change response body for html safe string if add_footer is true' do
|
107
|
+
expect(Bullet).to receive(:add_footer).exactly(3).times.and_return(true)
|
108
|
+
app.response = Support::ResponseDouble.new.tap do |response|
|
109
|
+
response.body = ActiveSupport::SafeBuffer.new('<html><head></head><body></body></html>')
|
110
|
+
end
|
111
|
+
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
112
|
+
|
113
|
+
expect(headers['Content-Length']).to eq((73 + middleware.send(:footer_note).length).to_s)
|
114
|
+
expect(response).to eq(%w[<html><head></head><body>footer<bullet></bullet><script></script></body></html>])
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should add the footer-text header for non-html requests when add_footer is true' do
|
118
|
+
allow(Bullet).to receive(:add_footer).at_least(:once).and_return(true)
|
119
|
+
allow(Bullet).to receive(:footer_info).and_return(['footer text'])
|
120
|
+
app.headers = {'Content-Type' => 'application/json'}
|
121
|
+
_, headers, _response = middleware.call({})
|
122
|
+
expect(headers).to include('X-bullet-footer-text' => '["footer text"]')
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should change response body if console_enabled is true' do
|
126
|
+
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
127
|
+
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
128
|
+
expect(headers['Content-Length']).to eq('56')
|
129
|
+
expect(response).to eq(%w[<html><head></head><body><bullet></bullet></body></html>])
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should change response body for html safe string if console_enabled is true' do
|
133
|
+
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
134
|
+
app.response = Support::ResponseDouble.new.tap do |response|
|
135
|
+
response.body = ActiveSupport::SafeBuffer.new('<html><head></head><body></body></html>')
|
136
|
+
end
|
137
|
+
_, headers, response = middleware.call('Content-Type' => 'text/html')
|
138
|
+
expect(headers['Content-Length']).to eq('56')
|
139
|
+
expect(response).to eq(%w[<html><head></head><body><bullet></bullet></body></html>])
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should add headers for non-html requests when console_enabled is true' do
|
143
|
+
allow(Bullet).to receive(:console_enabled?).at_least(:once).and_return(true)
|
144
|
+
allow(Bullet).to receive(:text_notifications).and_return(['text notifications'])
|
145
|
+
app.headers = {'Content-Type' => 'application/json'}
|
146
|
+
_, headers, _response = middleware.call({})
|
147
|
+
expect(headers).to include('X-bullet-console-text' => '["text notifications"]')
|
148
|
+
end
|
149
|
+
|
150
|
+
it "shouldn't change response body unnecessarily" do
|
151
|
+
expected_response = Support::ResponseDouble.new 'Actual body'
|
152
|
+
app.response = expected_response
|
153
|
+
_, _, response = middleware.call({})
|
154
|
+
expect(response).to eq(expected_response)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "shouldn't add headers unnecessarily" do
|
158
|
+
app.headers = {'Content-Type' => 'application/json'}
|
159
|
+
_, headers, _response = middleware.call({})
|
160
|
+
expect(headers).not_to include('X-bullet-footer-text')
|
161
|
+
expect(headers).not_to include('X-bullet-console-text')
|
162
|
+
end
|
163
|
+
|
164
|
+
context "when skip_http_headers is enabled" do
|
165
|
+
before do
|
166
|
+
allow(Bullet).to receive(:skip_http_headers).and_return(true)
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should include the footer but not the xhr script tag if add_footer is true' do
|
170
|
+
expect(Bullet).to receive(:add_footer).at_least(:once).and_return(true)
|
171
|
+
_, headers, response = middleware.call({})
|
172
|
+
|
173
|
+
expect(headers['Content-Length']).to eq((56 + middleware.send(:footer_note).length).to_s)
|
174
|
+
expect(response).to eq(%w[<html><head></head><body>footer<bullet></bullet></body></html>])
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should not include the xhr script tag if console_enabled is true' do
|
178
|
+
expect(Bullet).to receive(:console_enabled?).and_return(true)
|
179
|
+
_, headers, response = middleware.call({})
|
180
|
+
expect(headers['Content-Length']).to eq('56')
|
181
|
+
expect(response).to eq(%w[<html><head></head><body><bullet></bullet></body></html>])
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should not add the footer-text header for non-html requests when add_footer is true' do
|
185
|
+
allow(Bullet).to receive(:add_footer).at_least(:once).and_return(true)
|
186
|
+
app.headers = {'Content-Type' => 'application/json'}
|
187
|
+
_, headers, _response = middleware.call({})
|
188
|
+
expect(headers).not_to include('X-bullet-footer-text')
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'should not add headers for non-html requests when console_enabled is true' do
|
192
|
+
allow(Bullet).to receive(:console_enabled?).at_least(:once).and_return(true)
|
193
|
+
app.headers = {'Content-Type' => 'application/json'}
|
194
|
+
_, headers, _response = middleware.call({})
|
195
|
+
expect(headers).not_to include('X-bullet-console-text')
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'when skip_html_injection is enabled' do
|
201
|
+
it 'should not try to inject html' do
|
202
|
+
expected_response = Support::ResponseDouble.new 'Actual body'
|
203
|
+
app.response = expected_response
|
204
|
+
allow(Bullet).to receive(:notification?).and_return(true)
|
205
|
+
allow(Bullet).to receive(:skip_html_injection?).and_return(true)
|
206
|
+
expect(Bullet).to receive(:gather_inline_notifications).never
|
207
|
+
expect(middleware).to receive(:xhr_script).never
|
208
|
+
expect(Bullet).to receive(:perform_out_of_channel_notifications)
|
209
|
+
_, _, response = middleware.call('Content-Type' => 'text/html')
|
210
|
+
expect(response).to eq(expected_response)
|
211
|
+
end
|
86
212
|
end
|
87
213
|
end
|
88
214
|
|
@@ -98,8 +224,8 @@ module Bullet
|
|
98
224
|
|
99
225
|
context '#set_header' do
|
100
226
|
it 'should truncate headers to under 8kb' do
|
101
|
-
long_header = ['a' *
|
102
|
-
expected_res = (['a' *
|
227
|
+
long_header = ['a' * 1_024] * 10
|
228
|
+
expected_res = (['a' * 1_024] * 7).to_json
|
103
229
|
expect(middleware.set_header({}, 'Dummy-Header', long_header)).to eq(expected_res)
|
104
230
|
end
|
105
231
|
end
|
@@ -16,11 +16,11 @@ module Bullet
|
|
16
16
|
|
17
17
|
context '#similarly_associated' do
|
18
18
|
it 'should return similarly associated keys' do
|
19
|
-
expect(subject.similarly_associated('key1', Set.new([
|
19
|
+
expect(subject.similarly_associated('key1', Set.new(%w[value]))).to eq(%w[key1 key2])
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'should return empty if key does not exist' do
|
23
|
-
expect(subject.similarly_associated('key3', Set.new([
|
23
|
+
expect(subject.similarly_associated('key3', Set.new(%w[value]))).to be_empty
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
data/spec/bullet_spec.rb
CHANGED
@@ -17,9 +17,7 @@ describe Bullet, focused: true do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
context 'disable Bullet' do
|
20
|
-
before
|
21
|
-
Bullet.enable = false
|
22
|
-
end
|
20
|
+
before { Bullet.enable = false }
|
23
21
|
|
24
22
|
it 'should be disabled' do
|
25
23
|
expect(subject).to_not be_enable
|
@@ -27,8 +25,8 @@ describe Bullet, focused: true do
|
|
27
25
|
|
28
26
|
context 'enable Bullet again without patching again the orms' do
|
29
27
|
before do
|
30
|
-
expect(Bullet::Mongoid).not_to receive(:enable) if defined?
|
31
|
-
expect(Bullet::ActiveRecord).not_to receive(:enable) if defined?
|
28
|
+
expect(Bullet::Mongoid).not_to receive(:enable) if defined?(Bullet::Mongoid)
|
29
|
+
expect(Bullet::ActiveRecord).not_to receive(:enable) if defined?(Bullet::ActiveRecord)
|
32
30
|
Bullet.enable = true
|
33
31
|
end
|
34
32
|
|
@@ -42,9 +40,7 @@ describe Bullet, focused: true do
|
|
42
40
|
|
43
41
|
describe '#start?' do
|
44
42
|
context 'when bullet is disabled' do
|
45
|
-
before(:each)
|
46
|
-
Bullet.enable = false
|
47
|
-
end
|
43
|
+
before(:each) { Bullet.enable = false }
|
48
44
|
|
49
45
|
it 'should not be started' do
|
50
46
|
expect(Bullet).not_to be_start
|
@@ -53,28 +49,19 @@ describe Bullet, focused: true do
|
|
53
49
|
end
|
54
50
|
|
55
51
|
describe '#debug' do
|
56
|
-
before(:each)
|
57
|
-
$stdout = StringIO.new
|
58
|
-
end
|
52
|
+
before(:each) { $stdout = StringIO.new }
|
59
53
|
|
60
|
-
after(:each)
|
61
|
-
$stdout = STDOUT
|
62
|
-
end
|
54
|
+
after(:each) { $stdout = STDOUT }
|
63
55
|
|
64
56
|
context 'when debug is enabled' do
|
65
|
-
before(:each)
|
66
|
-
ENV['BULLET_DEBUG'] = 'true'
|
67
|
-
end
|
57
|
+
before(:each) { ENV['BULLET_DEBUG'] = 'true' }
|
68
58
|
|
69
|
-
after(:each)
|
70
|
-
ENV['BULLET_DEBUG'] = 'false'
|
71
|
-
end
|
59
|
+
after(:each) { ENV['BULLET_DEBUG'] = 'false' }
|
72
60
|
|
73
61
|
it 'should output debug information' do
|
74
62
|
Bullet.debug('debug_message', 'this is helpful information')
|
75
63
|
|
76
|
-
expect($stdout.string)
|
77
|
-
.to eq("[Bullet][debug_message] this is helpful information\n")
|
64
|
+
expect($stdout.string).to eq("[Bullet][debug_message] this is helpful information\n")
|
78
65
|
end
|
79
66
|
end
|
80
67
|
|
@@ -125,13 +112,7 @@ describe Bullet, focused: true do
|
|
125
112
|
end
|
126
113
|
|
127
114
|
context 'when called with Rack environment hash' do
|
128
|
-
let(:env) {
|
129
|
-
{
|
130
|
-
'REQUEST_METHOD' => 'GET',
|
131
|
-
'PATH_INFO' => '/path',
|
132
|
-
'QUERY_STRING' => 'foo=bar'
|
133
|
-
}
|
134
|
-
}
|
115
|
+
let(:env) { { 'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/path', 'QUERY_STRING' => 'foo=bar' } }
|
135
116
|
|
136
117
|
context "when env['REQUEST_URI'] is nil" do
|
137
118
|
before { env['REQUEST_URI'] = nil }
|
@@ -6,9 +6,7 @@ if active_record?
|
|
6
6
|
describe Bullet::Detector::Association, 'has_many' do
|
7
7
|
context 'post => comments' do
|
8
8
|
it 'should detect non preload post => comments' do
|
9
|
-
Post.all.each
|
10
|
-
post.comments.map(&:name)
|
11
|
-
end
|
9
|
+
Post.all.each { |post| post.comments.map(&:name) }
|
12
10
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
13
11
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
14
12
|
|
@@ -16,9 +14,7 @@ if active_record?
|
|
16
14
|
end
|
17
15
|
|
18
16
|
it 'should detect non preload post => comments for find_by_sql' do
|
19
|
-
Post.find_by_sql('SELECT * FROM posts').each
|
20
|
-
post.comments.map(&:name)
|
21
|
-
end
|
17
|
+
Post.find_by_sql('SELECT * FROM posts').each { |post| post.comments.map(&:name) }
|
22
18
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
23
19
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
24
20
|
|
@@ -26,9 +22,7 @@ if active_record?
|
|
26
22
|
end
|
27
23
|
|
28
24
|
it 'should detect preload with post => comments' do
|
29
|
-
Post.includes(:comments).each
|
30
|
-
post.comments.map(&:name)
|
31
|
-
end
|
25
|
+
Post.includes(:comments).each { |post| post.comments.map(&:name) }
|
32
26
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
33
27
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
34
28
|
|
@@ -65,9 +59,7 @@ if active_record?
|
|
65
59
|
end
|
66
60
|
|
67
61
|
it 'should detect non preload post => comments with empty?' do
|
68
|
-
Post.all.each
|
69
|
-
post.comments.empty?
|
70
|
-
end
|
62
|
+
Post.all.each { |post| post.comments.empty? }
|
71
63
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
72
64
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
73
65
|
|
@@ -76,9 +68,7 @@ if active_record?
|
|
76
68
|
|
77
69
|
it 'should detect non preload post => comments with include?' do
|
78
70
|
comment = Comment.last
|
79
|
-
Post.all.each
|
80
|
-
post.comments.include?(comment)
|
81
|
-
end
|
71
|
+
Post.all.each { |post| post.comments.include?(comment) }
|
82
72
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
83
73
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
84
74
|
|
@@ -86,9 +76,7 @@ if active_record?
|
|
86
76
|
end
|
87
77
|
|
88
78
|
it 'should not detect unused preload person => pets with empty?' do
|
89
|
-
Person.all.each
|
90
|
-
person.pets.empty?
|
91
|
-
end
|
79
|
+
Person.all.each { |person| person.pets.empty? }
|
92
80
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
93
81
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
94
82
|
|
@@ -98,11 +86,7 @@ if active_record?
|
|
98
86
|
|
99
87
|
context 'category => posts => comments' do
|
100
88
|
it 'should detect non preload category => posts => comments' do
|
101
|
-
Category.all.each
|
102
|
-
category.posts.each do |post|
|
103
|
-
post.comments.map(&:name)
|
104
|
-
end
|
105
|
-
end
|
89
|
+
Category.all.each { |category| category.posts.each { |post| post.comments.map(&:name) } }
|
106
90
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
107
91
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
108
92
|
|
@@ -111,11 +95,7 @@ if active_record?
|
|
111
95
|
end
|
112
96
|
|
113
97
|
it 'should detect preload category => posts, but no post => comments' do
|
114
|
-
Category.includes(:posts).each
|
115
|
-
category.posts.each do |post|
|
116
|
-
post.comments.map(&:name)
|
117
|
-
end
|
118
|
-
end
|
98
|
+
Category.includes(:posts).each { |category| category.posts.each { |post| post.comments.map(&:name) } }
|
119
99
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
120
100
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
121
101
|
|
@@ -124,11 +104,7 @@ if active_record?
|
|
124
104
|
end
|
125
105
|
|
126
106
|
it 'should detect preload with category => posts => comments' do
|
127
|
-
Category.includes(posts: :comments).each
|
128
|
-
category.posts.each do |post|
|
129
|
-
post.comments.map(&:name)
|
130
|
-
end
|
131
|
-
end
|
107
|
+
Category.includes(posts: :comments).each { |category| category.posts.each { |post| post.comments.map(&:name) } }
|
132
108
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
133
109
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
134
110
|
|
@@ -137,9 +113,7 @@ if active_record?
|
|
137
113
|
|
138
114
|
it 'should detect preload with category => posts => comments with posts.id > 0' do
|
139
115
|
Category.includes(posts: :comments).where('posts.id > 0').references(:posts).each do |category|
|
140
|
-
category.posts.each
|
141
|
-
post.comments.map(&:name)
|
142
|
-
end
|
116
|
+
category.posts.each { |post| post.comments.map(&:name) }
|
143
117
|
end
|
144
118
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
145
119
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
@@ -156,9 +130,7 @@ if active_record?
|
|
156
130
|
end
|
157
131
|
|
158
132
|
it 'should detect unused preload with post => commnets, no category => posts' do
|
159
|
-
Category.includes(posts: :comments).each
|
160
|
-
category.posts.map(&:name)
|
161
|
-
end
|
133
|
+
Category.includes(posts: :comments).each { |category| category.posts.map(&:name) }
|
162
134
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
163
135
|
expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
|
164
136
|
|
@@ -212,9 +184,7 @@ if active_record?
|
|
212
184
|
end
|
213
185
|
|
214
186
|
it 'should detect unused preload with category => entries, but not with category => posts' do
|
215
|
-
Category.includes(%i[posts entries]).each
|
216
|
-
category.posts.map(&:name)
|
217
|
-
end
|
187
|
+
Category.includes(%i[posts entries]).each { |category| category.posts.map(&:name) }
|
218
188
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
219
189
|
expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Category, :posts)
|
220
190
|
expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :entries)
|
@@ -225,9 +195,7 @@ if active_record?
|
|
225
195
|
|
226
196
|
context 'post => comment' do
|
227
197
|
it 'should detect unused preload with post => comments' do
|
228
|
-
Post.includes(:comments).each
|
229
|
-
post.comments.first&.name
|
230
|
-
end
|
198
|
+
Post.includes(:comments).each { |post| post.comments.first&.name }
|
231
199
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
232
200
|
expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :comments)
|
233
201
|
|
@@ -272,9 +240,7 @@ if active_record?
|
|
272
240
|
|
273
241
|
context 'scope for_category_name' do
|
274
242
|
it 'should detect preload with post => category' do
|
275
|
-
Post.in_category_name('first').references(:categories).each
|
276
|
-
post.category.name
|
277
|
-
end
|
243
|
+
Post.in_category_name('first').references(:categories).each { |post| post.category.name }
|
278
244
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
279
245
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
280
246
|
|
@@ -292,9 +258,7 @@ if active_record?
|
|
292
258
|
|
293
259
|
context 'scope preload_comments' do
|
294
260
|
it 'should detect preload post => comments with scope' do
|
295
|
-
Post.preload_comments.each
|
296
|
-
post.comments.map(&:name)
|
297
|
-
end
|
261
|
+
Post.preload_comments.each { |post| post.comments.map(&:name) }
|
298
262
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
299
263
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
300
264
|
|
@@ -314,9 +278,7 @@ if active_record?
|
|
314
278
|
describe Bullet::Detector::Association, 'belongs_to' do
|
315
279
|
context 'comment => post' do
|
316
280
|
it 'should detect non preload with comment => post' do
|
317
|
-
Comment.all.each
|
318
|
-
comment.post.name
|
319
|
-
end
|
281
|
+
Comment.all.each { |comment| comment.post.name }
|
320
282
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
321
283
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
322
284
|
|
@@ -332,9 +294,7 @@ if active_record?
|
|
332
294
|
end
|
333
295
|
|
334
296
|
it 'should detect preload with comment => post' do
|
335
|
-
Comment.includes(:post).each
|
336
|
-
comment.post.name
|
337
|
-
end
|
297
|
+
Comment.includes(:post).each { |comment| comment.post.name }
|
338
298
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
339
299
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
340
300
|
|
@@ -371,9 +331,7 @@ if active_record?
|
|
371
331
|
|
372
332
|
context 'comment => post => category' do
|
373
333
|
it 'should detect non preload association with comment => post' do
|
374
|
-
Comment.all.each
|
375
|
-
comment.post.category.name
|
376
|
-
end
|
334
|
+
Comment.all.each { |comment| comment.post.category.name }
|
377
335
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
378
336
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
379
337
|
|
@@ -390,9 +348,7 @@ if active_record?
|
|
390
348
|
end
|
391
349
|
|
392
350
|
it 'should detect non preload association with post => category' do
|
393
|
-
Comment.includes(:post).each
|
394
|
-
comment.post.category.name
|
395
|
-
end
|
351
|
+
Comment.includes(:post).each { |comment| comment.post.category.name }
|
396
352
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
397
353
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
398
354
|
|
@@ -400,9 +356,7 @@ if active_record?
|
|
400
356
|
end
|
401
357
|
|
402
358
|
it 'should not detect unpreload association' do
|
403
|
-
Comment.includes(post: :category).each
|
404
|
-
comment.post.category.name
|
405
|
-
end
|
359
|
+
Comment.includes(post: :category).each { |comment| comment.post.category.name }
|
406
360
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
407
361
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
408
362
|
|
@@ -412,9 +366,8 @@ if active_record?
|
|
412
366
|
|
413
367
|
context 'comment => author, post => writer' do
|
414
368
|
it 'should detect non preloaded writer' do
|
415
|
-
Comment.includes(%i[author post]).where(['base_users.id = ?', BaseUser.first]).references(:base_users)
|
416
|
-
comment.post.writer.name
|
417
|
-
end
|
369
|
+
Comment.includes(%i[author post]).where(['base_users.id = ?', BaseUser.first]).references(:base_users)
|
370
|
+
.each { |comment| comment.post.writer.name }
|
418
371
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
419
372
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
420
373
|
|
@@ -422,9 +375,9 @@ if active_record?
|
|
422
375
|
end
|
423
376
|
|
424
377
|
it 'should detect unused preload with comment => author' do
|
425
|
-
Comment.includes([:author, { post: :writer }]).where(['base_users.id = ?', BaseUser.first]).references(
|
426
|
-
|
427
|
-
|
378
|
+
Comment.includes([:author, { post: :writer }]).where(['base_users.id = ?', BaseUser.first]).references(
|
379
|
+
:base_users
|
380
|
+
).each { |comment| comment.post.writer.name }
|
428
381
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
429
382
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
430
383
|
|
@@ -442,11 +395,7 @@ if active_record?
|
|
442
395
|
end
|
443
396
|
|
444
397
|
it 'should not raise a stack error from posts to category' do
|
445
|
-
expect {
|
446
|
-
Comment.includes(post: :category).each do |com|
|
447
|
-
com.post.category
|
448
|
-
end
|
449
|
-
}.not_to raise_error
|
398
|
+
expect { Comment.includes(post: :category).each { |com| com.post.category } }.not_to raise_error
|
450
399
|
end
|
451
400
|
end
|
452
401
|
end
|
@@ -454,9 +403,7 @@ if active_record?
|
|
454
403
|
describe Bullet::Detector::Association, 'has_and_belongs_to_many' do
|
455
404
|
context 'students <=> teachers' do
|
456
405
|
it 'should detect non preload associations' do
|
457
|
-
Student.all.each
|
458
|
-
student.teachers.map(&:name)
|
459
|
-
end
|
406
|
+
Student.all.each { |student| student.teachers.map(&:name) }
|
460
407
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
461
408
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
462
409
|
|
@@ -464,9 +411,7 @@ if active_record?
|
|
464
411
|
end
|
465
412
|
|
466
413
|
it 'should detect preload associations' do
|
467
|
-
Student.includes(:teachers).each
|
468
|
-
student.teachers.map(&:name)
|
469
|
-
end
|
414
|
+
Student.includes(:teachers).each { |student| student.teachers.map(&:name) }
|
470
415
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
471
416
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
472
417
|
|
@@ -490,9 +435,7 @@ if active_record?
|
|
490
435
|
end
|
491
436
|
|
492
437
|
it 'should detect non preload student => teachers with empty?' do
|
493
|
-
Student.all.each
|
494
|
-
student.teachers.empty?
|
495
|
-
end
|
438
|
+
Student.all.each { |student| student.teachers.empty? }
|
496
439
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
497
440
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
498
441
|
|
@@ -504,9 +447,7 @@ if active_record?
|
|
504
447
|
describe Bullet::Detector::Association, 'has_many :through' do
|
505
448
|
context 'firm => clients' do
|
506
449
|
it 'should detect non preload associations' do
|
507
|
-
Firm.all.each
|
508
|
-
firm.clients.map(&:name)
|
509
|
-
end
|
450
|
+
Firm.all.each { |firm| firm.clients.map(&:name) }
|
510
451
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
511
452
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
512
453
|
|
@@ -514,9 +455,7 @@ if active_record?
|
|
514
455
|
end
|
515
456
|
|
516
457
|
it 'should detect preload associations' do
|
517
|
-
Firm.includes(:clients).each
|
518
|
-
firm.clients.map(&:name)
|
519
|
-
end
|
458
|
+
Firm.includes(:clients).each { |firm| firm.clients.map(&:name) }
|
520
459
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
521
460
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
522
461
|
|
@@ -542,9 +481,7 @@ if active_record?
|
|
542
481
|
|
543
482
|
context 'firm => clients => groups' do
|
544
483
|
it 'should detect non preload associations' do
|
545
|
-
Firm.all.each
|
546
|
-
firm.groups.map(&:name)
|
547
|
-
end
|
484
|
+
Firm.all.each { |firm| firm.groups.map(&:name) }
|
548
485
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
549
486
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
550
487
|
|
@@ -552,9 +489,7 @@ if active_record?
|
|
552
489
|
end
|
553
490
|
|
554
491
|
it 'should detect preload associations' do
|
555
|
-
Firm.includes(:groups).each
|
556
|
-
firm.groups.map(&:name)
|
557
|
-
end
|
492
|
+
Firm.includes(:groups).each { |firm| firm.groups.map(&:name) }
|
558
493
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
559
494
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
560
495
|
|
@@ -582,9 +517,7 @@ if active_record?
|
|
582
517
|
describe Bullet::Detector::Association, 'has_one' do
|
583
518
|
context 'company => address' do
|
584
519
|
it 'should detect non preload association' do
|
585
|
-
Company.all.each
|
586
|
-
company.address.name
|
587
|
-
end
|
520
|
+
Company.all.each { |company| company.address.name }
|
588
521
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
589
522
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
590
523
|
|
@@ -592,9 +525,7 @@ if active_record?
|
|
592
525
|
end
|
593
526
|
|
594
527
|
it 'should detect preload association' do
|
595
|
-
Company.includes(:address).each
|
596
|
-
company.address.name
|
597
|
-
end
|
528
|
+
Company.includes(:address).each { |company| company.address.name }
|
598
529
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
599
530
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
600
531
|
|
@@ -630,6 +561,42 @@ if active_record?
|
|
630
561
|
end
|
631
562
|
end
|
632
563
|
|
564
|
+
describe Bullet::Detector::Association, 'has_one :through' do
|
565
|
+
context 'user => attachment' do
|
566
|
+
it 'should detect non preload associations' do
|
567
|
+
User.all.each { |user| user.submission_attachment.file_name }
|
568
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
569
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
570
|
+
|
571
|
+
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(User, :submission_attachment)
|
572
|
+
end
|
573
|
+
|
574
|
+
it 'should detect preload associations' do
|
575
|
+
User.includes(:submission_attachment).each { |user| user.submission_attachment.file_name }
|
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
|
+
|
582
|
+
it 'should not detect preload associations' do
|
583
|
+
User.all.map(&:name)
|
584
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
585
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
586
|
+
|
587
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
588
|
+
end
|
589
|
+
|
590
|
+
it 'should detect unused preload associations' do
|
591
|
+
User.includes(:submission_attachment).map(&:name)
|
592
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
593
|
+
expect(Bullet::Detector::Association).to be_unused_preload_associations_for(User, :submission_attachment)
|
594
|
+
|
595
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
633
600
|
describe Bullet::Detector::Association, 'call one association that in possible objects' do
|
634
601
|
it 'should not detect preload association' do
|
635
602
|
Post.all
|
@@ -688,9 +655,7 @@ if active_record?
|
|
688
655
|
describe Bullet::Detector::Association, 'STI' do
|
689
656
|
context 'page => author' do
|
690
657
|
it 'should detect non preload associations' do
|
691
|
-
Page.all.each
|
692
|
-
page.author.name
|
693
|
-
end
|
658
|
+
Page.all.each { |page| page.author.name }
|
694
659
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
695
660
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
696
661
|
|
@@ -698,9 +663,7 @@ if active_record?
|
|
698
663
|
end
|
699
664
|
|
700
665
|
it 'should detect preload associations' do
|
701
|
-
Page.includes(:author).each
|
702
|
-
page.author.name
|
703
|
-
end
|
666
|
+
Page.includes(:author).each { |page| page.author.name }
|
704
667
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
705
668
|
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
706
669
|
|
@@ -729,9 +692,7 @@ if active_record?
|
|
729
692
|
after { Bullet.n_plus_one_query_enable = true }
|
730
693
|
|
731
694
|
it 'should not detect n plus one query' do
|
732
|
-
Post.all.each
|
733
|
-
post.comments.map(&:name)
|
734
|
-
end
|
695
|
+
Post.all.each { |post| post.comments.map(&:name) }
|
735
696
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
736
697
|
|
737
698
|
expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
|
@@ -760,9 +721,7 @@ if active_record?
|
|
760
721
|
end
|
761
722
|
|
762
723
|
it 'should still detect n plus one query' do
|
763
|
-
Post.all.each
|
764
|
-
post.comments.map(&:name)
|
765
|
-
end
|
724
|
+
Post.all.each { |post| post.comments.map(&:name) }
|
766
725
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
767
726
|
|
768
727
|
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
|
@@ -775,9 +734,7 @@ if active_record?
|
|
775
734
|
after { Bullet.clear_whitelist }
|
776
735
|
|
777
736
|
it 'should not detect n plus one query' do
|
778
|
-
Post.all.each
|
779
|
-
post.comments.map(&:name)
|
780
|
-
end
|
737
|
+
Post.all.each { |post| post.comments.map(&:name) }
|
781
738
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
782
739
|
|
783
740
|
expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
|
@@ -806,9 +763,7 @@ if active_record?
|
|
806
763
|
end
|
807
764
|
|
808
765
|
it 'should still detect n plus one query' do
|
809
|
-
Post.all.each
|
810
|
-
post.comments.map(&:name)
|
811
|
-
end
|
766
|
+
Post.all.each { |post| post.comments.map(&:name) }
|
812
767
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
813
768
|
|
814
769
|
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
|