bullet 4.13.1 → 5.5.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +7 -11
- data/CHANGELOG.md +62 -3
- data/Gemfile.mongoid +0 -2
- data/Gemfile.mongoid-4.0 +1 -5
- data/{Gemfile.mongoid-2.8 → Gemfile.mongoid-5.0} +2 -6
- data/{Gemfile.mongoid-2.5 → Gemfile.mongoid-6.0} +2 -6
- data/Gemfile.rails-4.0 +2 -5
- data/Gemfile.rails-4.1 +2 -5
- data/{Gemfile.rails-3.0 → Gemfile.rails-4.2} +3 -6
- data/{Gemfile.rails-3.1 → Gemfile.rails-5.0} +2 -6
- data/Hacking.md +1 -0
- data/README.md +39 -7
- data/bullet.gemspec +1 -1
- data/lib/bullet/active_record4.rb +109 -33
- data/lib/bullet/active_record41.rb +99 -37
- data/lib/bullet/active_record42.rb +251 -0
- data/lib/bullet/active_record5.rb +243 -0
- data/lib/bullet/dependency.rb +34 -28
- data/lib/bullet/detector/association.rb +16 -16
- data/lib/bullet/detector/counter_cache.rb +13 -13
- data/lib/bullet/detector/n_plus_one_query.rb +30 -35
- data/lib/bullet/detector/unused_eager_loading.rb +12 -11
- data/lib/bullet/ext/object.rb +4 -2
- data/lib/bullet/{mongoid3x.rb → mongoid5x.rb} +3 -3
- data/lib/bullet/{mongoid2x.rb → mongoid6x.rb} +12 -12
- data/lib/bullet/notification/base.rb +9 -13
- data/lib/bullet/notification/n_plus_one_query.rb +8 -6
- data/lib/bullet/notification/unused_eager_loading.rb +18 -1
- data/lib/bullet/rack.rb +28 -16
- data/lib/bullet/stack_trace_filter.rb +34 -0
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +48 -14
- data/spec/bullet/detector/counter_cache_spec.rb +8 -8
- data/spec/bullet/detector/n_plus_one_query_spec.rb +46 -31
- data/spec/bullet/detector/unused_eager_loading_spec.rb +17 -3
- data/spec/bullet/ext/object_spec.rb +6 -0
- data/spec/bullet/notification/base_spec.rb +4 -29
- data/spec/bullet/notification/n_plus_one_query_spec.rb +4 -4
- data/spec/bullet/notification/unused_eager_loading_spec.rb +3 -3
- data/spec/bullet/rack_spec.rb +38 -7
- data/spec/bullet_spec.rb +93 -0
- data/spec/integration/active_record4/association_spec.rb +112 -4
- data/spec/integration/{active_record3 → active_record5}/association_spec.rb +121 -15
- data/spec/integration/counter_cache_spec.rb +24 -1
- data/spec/models/category.rb +4 -1
- data/spec/models/comment.rb +2 -0
- data/spec/models/post.rb +7 -2
- data/spec/models/reply.rb +3 -0
- data/spec/models/submission.rb +1 -1
- data/spec/spec_helper.rb +3 -5
- data/spec/support/mongo_seed.rb +13 -0
- data/spec/support/sqlite_seed.rb +15 -6
- data/test.sh +4 -10
- data/update.sh +7 -0
- metadata +21 -23
- data/Gemfile.mongoid-2.4 +0 -19
- data/Gemfile.mongoid-2.6 +0 -19
- data/Gemfile.mongoid-2.7 +0 -19
- data/Gemfile.mongoid-3.0 +0 -19
- data/Gemfile.mongoid-3.1 +0 -19
- data/Gemfile.rails-3.2 +0 -19
- data/lib/bullet/active_record3.rb +0 -154
- data/lib/bullet/active_record3x.rb +0 -134
|
@@ -5,7 +5,8 @@ module Bullet
|
|
|
5
5
|
describe UnusedEagerLoading do
|
|
6
6
|
before(:all) do
|
|
7
7
|
@post = Post.first
|
|
8
|
-
@post2 = Post.
|
|
8
|
+
@post2 = Post.all[1]
|
|
9
|
+
@post3 = Post.last
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
context ".call_associations" do
|
|
@@ -38,9 +39,11 @@ module Bullet
|
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
context ".check_unused_preload_associations" do
|
|
42
|
+
let(:paths) { ["/dir1", "/dir1/subdir"] }
|
|
41
43
|
it "should create notification if object_association_diff is not empty" do
|
|
42
44
|
UnusedEagerLoading.add_object_associations(@post, :association)
|
|
43
|
-
|
|
45
|
+
allow(UnusedEagerLoading).to receive(:caller_in_project).and_return(paths)
|
|
46
|
+
expect(UnusedEagerLoading).to receive(:create_notification).with(paths, "Post", [:association])
|
|
44
47
|
UnusedEagerLoading.check_unused_preload_associations
|
|
45
48
|
end
|
|
46
49
|
|
|
@@ -72,7 +75,18 @@ module Bullet
|
|
|
72
75
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
|
|
73
76
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
|
|
74
77
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
|
|
75
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@
|
|
78
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association2)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should vmerge objects recursively, associations pair for existing eager_loadings" do
|
|
82
|
+
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
|
|
83
|
+
UnusedEagerLoading.add_eager_loadings([@post, @post3], :association1)
|
|
84
|
+
UnusedEagerLoading.add_eager_loadings([@post, @post3], :association2)
|
|
85
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
|
|
86
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
|
|
87
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association1)
|
|
88
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post3.bullet_key], :association1)
|
|
89
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post3.bullet_key], :association2)
|
|
76
90
|
end
|
|
77
91
|
|
|
78
92
|
it "should delete objects, associations pair for existing eager_loadings" do
|
|
@@ -27,5 +27,11 @@ describe Object do
|
|
|
27
27
|
expect(post.primary_key_value).to eq(post.name)
|
|
28
28
|
Post.primary_key = 'id'
|
|
29
29
|
end
|
|
30
|
+
|
|
31
|
+
it "should return value for multiple primary keys" do
|
|
32
|
+
post = Post.first
|
|
33
|
+
allow(Post).to receive(:primary_keys).and_return([:category_id, :writer_id])
|
|
34
|
+
expect(post.primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
|
|
35
|
+
end
|
|
30
36
|
end
|
|
31
37
|
end
|
|
@@ -30,14 +30,14 @@ module Bullet
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "should return blank if no user available" do
|
|
33
|
-
temp_env_variable("USER","") do
|
|
33
|
+
temp_env_variable("USER", "") do
|
|
34
34
|
expect(subject).to receive(:`).with("whoami").and_return("")
|
|
35
35
|
expect(subject.whoami).to eq("")
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
it "should return blank if whoami is not available" do
|
|
40
|
-
temp_env_variable("USER","") do
|
|
40
|
+
temp_env_variable("USER", "") do
|
|
41
41
|
expect(subject).to receive(:`).with("whoami").and_raise(Errno::ENOENT)
|
|
42
42
|
expect(subject.whoami).to eq("")
|
|
43
43
|
end
|
|
@@ -56,33 +56,8 @@ module Bullet
|
|
|
56
56
|
context "#body_with_caller" do
|
|
57
57
|
it "should return body" do
|
|
58
58
|
allow(subject).to receive(:body).and_return("body")
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
context "#standard_notice" do
|
|
64
|
-
it "should return title + body" do
|
|
65
|
-
allow(subject).to receive(:title).and_return("title")
|
|
66
|
-
allow(subject).to receive(:body).and_return("body")
|
|
67
|
-
expect(subject.standard_notice).to eq("title\nbody")
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
context "#full_notice" do
|
|
72
|
-
it "should return whoami + url + title + body_with_caller" do
|
|
73
|
-
allow(subject).to receive(:whoami).and_return("whoami")
|
|
74
|
-
allow(subject).to receive(:url).and_return("url")
|
|
75
|
-
allow(subject).to receive(:title).and_return("title")
|
|
76
|
-
allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
|
|
77
|
-
expect(subject.full_notice).to eq("whoami\nurl\ntitle\nbody_with_caller")
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it "should return url + title + body_with_caller" do
|
|
81
|
-
allow(subject).to receive(:whoami).and_return("")
|
|
82
|
-
allow(subject).to receive(:url).and_return("url")
|
|
83
|
-
allow(subject).to receive(:title).and_return("title")
|
|
84
|
-
allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
|
|
85
|
-
expect(subject.full_notice).to eq("url\ntitle\nbody_with_caller")
|
|
59
|
+
allow(subject).to receive(:call_stack_messages).and_return("call_stack_messages")
|
|
60
|
+
expect(subject.body_with_caller).to eq("body\ncall_stack_messages\n")
|
|
86
61
|
end
|
|
87
62
|
end
|
|
88
63
|
|
|
@@ -5,10 +5,10 @@ module Bullet
|
|
|
5
5
|
describe NPlusOneQuery do
|
|
6
6
|
subject { NPlusOneQuery.new([["caller1", "caller2"]], Post, [:comments, :votes], "path") }
|
|
7
7
|
|
|
8
|
-
it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :
|
|
9
|
-
it { expect([
|
|
10
|
-
it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :
|
|
11
|
-
it { expect(subject.title).to eq("
|
|
8
|
+
it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n") }
|
|
9
|
+
it { expect([subject.body_with_caller, subject.body_with_caller]).to eq([ " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n", " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nCall stack\n caller1\n caller2\n" ]) }
|
|
10
|
+
it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]") }
|
|
11
|
+
it { expect(subject.title).to eq("USE eager loading in path") }
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
end
|
|
@@ -3,10 +3,10 @@ require 'spec_helper'
|
|
|
3
3
|
module Bullet
|
|
4
4
|
module Notification
|
|
5
5
|
describe UnusedEagerLoading do
|
|
6
|
-
subject { UnusedEagerLoading.new(Post, [:comments, :votes], "path") }
|
|
6
|
+
subject { UnusedEagerLoading.new([""], Post, [:comments, :votes], "path") }
|
|
7
7
|
|
|
8
|
-
it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :
|
|
9
|
-
it { expect(subject.title).to eq("
|
|
8
|
+
it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :includes => [:comments, :votes]") }
|
|
9
|
+
it { expect(subject.title).to eq("AVOID eager loading in path") }
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
data/spec/bullet/rack_spec.rb
CHANGED
|
@@ -60,26 +60,26 @@ module Bullet
|
|
|
60
60
|
it "should return original response body" do
|
|
61
61
|
expected_response = Support::ResponseDouble.new "Actual body"
|
|
62
62
|
app.response = expected_response
|
|
63
|
-
_, _, response = middleware.call(
|
|
63
|
+
_, _, response = middleware.call({})
|
|
64
64
|
expect(response).to eq(expected_response)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
it "should change response body if notification is active" do
|
|
68
|
-
expect(Bullet).to receive(:notification?).and_return(true)
|
|
68
|
+
expect(Bullet).to receive(:notification?).and_return(true)
|
|
69
69
|
expect(Bullet).to receive(:gather_inline_notifications).and_return("<bullet></bullet>")
|
|
70
70
|
expect(Bullet).to receive(:perform_out_of_channel_notifications)
|
|
71
|
-
status, headers, response = middleware.call(
|
|
71
|
+
status, headers, response = middleware.call({"Content-Type" => "text/html"})
|
|
72
72
|
expect(headers["Content-Length"]).to eq("56")
|
|
73
|
-
expect(response).to eq(["<html><head></head><body></body></html
|
|
73
|
+
expect(response).to eq(["<html><head></head><body><bullet></bullet></body></html>"])
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
it "should set the right Content-Length if response body contains accents" do
|
|
77
77
|
response = Support::ResponseDouble.new
|
|
78
78
|
response.body = "<html><head></head><body>é</body></html>"
|
|
79
79
|
app.response = response
|
|
80
|
-
expect(Bullet).to receive(:notification?).and_return(true)
|
|
80
|
+
expect(Bullet).to receive(:notification?).and_return(true)
|
|
81
81
|
expect(Bullet).to receive(:gather_inline_notifications).and_return("<bullet></bullet>")
|
|
82
|
-
status, headers, response = middleware.call(
|
|
82
|
+
status, headers, response = middleware.call({"Content-Type" => "text/html"})
|
|
83
83
|
expect(headers["Content-Length"]).to eq("58")
|
|
84
84
|
end
|
|
85
85
|
end
|
|
@@ -89,7 +89,38 @@ module Bullet
|
|
|
89
89
|
|
|
90
90
|
it "should not call Bullet.start_request" do
|
|
91
91
|
expect(Bullet).not_to receive(:start_request)
|
|
92
|
-
middleware.call(
|
|
92
|
+
middleware.call({})
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe "#response_body" do
|
|
98
|
+
let(:response) { double }
|
|
99
|
+
let(:body_string) { "<html><body>My Body</body></html>" }
|
|
100
|
+
|
|
101
|
+
context "when `response` responds to `body`" do
|
|
102
|
+
before { allow(response).to receive(:body).and_return(body) }
|
|
103
|
+
|
|
104
|
+
context "when `body` returns an Array" do
|
|
105
|
+
let(:body) { [body_string, 'random string'] }
|
|
106
|
+
it "should return the plain body string" do
|
|
107
|
+
expect(middleware.response_body(response)).to eq body_string
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context "when `body` does not return an Array" do
|
|
112
|
+
let(:body) { body_string }
|
|
113
|
+
it "should return the plain body string" do
|
|
114
|
+
expect(middleware.response_body(response)).to eq body_string
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "when `response` does not respond to `body`" do
|
|
120
|
+
before { allow(response).to receive(:first).and_return(body_string) }
|
|
121
|
+
|
|
122
|
+
it "should return the plain body string" do
|
|
123
|
+
expect(middleware.response_body(response)).to eq body_string
|
|
93
124
|
end
|
|
94
125
|
end
|
|
95
126
|
end
|
data/spec/bullet_spec.rb
CHANGED
|
@@ -38,4 +38,97 @@ describe Bullet, focused: true do
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
describe '#start?' do
|
|
43
|
+
context 'when bullet is disabled' do
|
|
44
|
+
before(:each) do
|
|
45
|
+
Bullet.enable = false
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'should not be started' do
|
|
49
|
+
expect(Bullet).not_to be_start
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe '#debug' do
|
|
55
|
+
before(:each) do
|
|
56
|
+
$stdout = StringIO.new
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
after(:each) do
|
|
60
|
+
$stdout = STDOUT
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'when debug is enabled' do
|
|
64
|
+
before(:each) do
|
|
65
|
+
ENV['BULLET_DEBUG'] = 'true'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
after(:each) do
|
|
69
|
+
ENV['BULLET_DEBUG'] = 'false'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should output debug information' do
|
|
73
|
+
Bullet.debug('debug_message', 'this is helpful information')
|
|
74
|
+
|
|
75
|
+
expect($stdout.string)
|
|
76
|
+
.to eq("[Bullet][debug_message] this is helpful information\n")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context 'when debug is disabled' do
|
|
81
|
+
it 'should output debug information' do
|
|
82
|
+
Bullet.debug('debug_message', 'this is helpful information')
|
|
83
|
+
|
|
84
|
+
expect($stdout.string).to be_empty
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe '#add_whitelist' do
|
|
90
|
+
context "for 'special' class names" do
|
|
91
|
+
it 'is added to the whitelist successfully' do
|
|
92
|
+
Bullet.add_whitelist(:type => :n_plus_one_query, :class_name => 'Klass', :association => :department)
|
|
93
|
+
expect(Bullet.get_whitelist_associations(:n_plus_one_query, 'Klass')).to include :department
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe '#perform_out_of_channel_notifications' do
|
|
99
|
+
let(:notification) { double }
|
|
100
|
+
|
|
101
|
+
before do
|
|
102
|
+
allow(Bullet).to receive(:for_each_active_notifier_with_notification).and_yield(notification)
|
|
103
|
+
allow(notification).to receive(:notify_out_of_channel)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context 'when called with Rack environment hash' do
|
|
107
|
+
let(:env) {
|
|
108
|
+
{
|
|
109
|
+
'REQUEST_METHOD' => 'GET',
|
|
110
|
+
'PATH_INFO' => '/path',
|
|
111
|
+
'QUERY_STRING' => 'foo=bar',
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
context "when env['REQUEST_URI'] is nil" do
|
|
116
|
+
before { env['REQUEST_URI'] = nil }
|
|
117
|
+
|
|
118
|
+
it 'should notification.url is built' do
|
|
119
|
+
expect(notification).to receive(:url=).with('GET /path?foo=bar')
|
|
120
|
+
Bullet.perform_out_of_channel_notifications(env)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "when env['REQUEST_URI'] is present" do
|
|
125
|
+
before { env['REQUEST_URI'] = 'http://example.com/path' }
|
|
126
|
+
|
|
127
|
+
it "should notification.url is env['REQUEST_URI']" do
|
|
128
|
+
expect(notification).to receive(:url=).with('GET http://example.com/path')
|
|
129
|
+
Bullet.perform_out_of_channel_notifications(env)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
41
134
|
end
|
|
@@ -13,6 +13,16 @@ if !mongoid? && active_record4?
|
|
|
13
13
|
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
it "should detect non preload post => comments for find_by_sql" do
|
|
17
|
+
Post.find_by_sql("SELECT * FROM posts").each do |post|
|
|
18
|
+
post.comments.map(&:name)
|
|
19
|
+
end
|
|
20
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
21
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
22
|
+
|
|
23
|
+
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
|
|
24
|
+
end
|
|
25
|
+
|
|
16
26
|
it "should detect preload with post => comments" do
|
|
17
27
|
Post.includes(:comments).each do |post|
|
|
18
28
|
post.comments.map(&:name)
|
|
@@ -72,6 +82,16 @@ if !mongoid? && active_record4?
|
|
|
72
82
|
|
|
73
83
|
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
|
|
74
84
|
end
|
|
85
|
+
|
|
86
|
+
it "should not detect unused preload person => pets with empty?" do
|
|
87
|
+
Person.all.each do |person|
|
|
88
|
+
person.pets.empty?
|
|
89
|
+
end
|
|
90
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
91
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
92
|
+
|
|
93
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
94
|
+
end
|
|
75
95
|
end
|
|
76
96
|
|
|
77
97
|
context "category => posts => comments" do
|
|
@@ -204,7 +224,7 @@ if !mongoid? && active_record4?
|
|
|
204
224
|
context "post => comment" do
|
|
205
225
|
it "should detect unused preload with post => comments" do
|
|
206
226
|
Post.includes(:comments).each do |post|
|
|
207
|
-
post.comments.first.name
|
|
227
|
+
post.comments.first.name if post.comments.first
|
|
208
228
|
end
|
|
209
229
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
210
230
|
expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :comments)
|
|
@@ -219,6 +239,20 @@ if !mongoid? && active_record4?
|
|
|
219
239
|
|
|
220
240
|
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
221
241
|
end
|
|
242
|
+
|
|
243
|
+
it "should not detect unused preload with category => posts" do
|
|
244
|
+
category = Category.first
|
|
245
|
+
category.draft_post.destroy!
|
|
246
|
+
post = category.draft_post
|
|
247
|
+
post.update_attributes!(link: true)
|
|
248
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
249
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
250
|
+
|
|
251
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
252
|
+
|
|
253
|
+
Support::SqliteSeed.setup_db
|
|
254
|
+
Support::SqliteSeed.seed_db
|
|
255
|
+
end
|
|
222
256
|
end
|
|
223
257
|
|
|
224
258
|
context "category => posts => writer" do
|
|
@@ -313,7 +347,7 @@ if !mongoid? && active_record4?
|
|
|
313
347
|
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
314
348
|
end
|
|
315
349
|
|
|
316
|
-
it "should detect unused preload with
|
|
350
|
+
it "should detect unused preload with comment => post" do
|
|
317
351
|
Comment.includes(:post).map(&:name)
|
|
318
352
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
319
353
|
expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Comment, :post)
|
|
@@ -333,6 +367,15 @@ if !mongoid? && active_record4?
|
|
|
333
367
|
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
|
|
334
368
|
end
|
|
335
369
|
|
|
370
|
+
it "should not detect non preload association with only one comment" do
|
|
371
|
+
Comment.first.post.category.name
|
|
372
|
+
|
|
373
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
374
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
375
|
+
|
|
376
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
377
|
+
end
|
|
378
|
+
|
|
336
379
|
it "should detect non preload association with post => category" do
|
|
337
380
|
Comment.includes(:post).each do |comment|
|
|
338
381
|
comment.post.category.name
|
|
@@ -432,6 +475,16 @@ if !mongoid? && active_record4?
|
|
|
432
475
|
|
|
433
476
|
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
434
477
|
end
|
|
478
|
+
|
|
479
|
+
it "should detect non preload student => teachers with empty?" do
|
|
480
|
+
Student.all.each do |student|
|
|
481
|
+
student.teachers.empty?
|
|
482
|
+
end
|
|
483
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
484
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
485
|
+
|
|
486
|
+
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Student, :teachers)
|
|
487
|
+
end
|
|
435
488
|
end
|
|
436
489
|
end
|
|
437
490
|
|
|
@@ -515,6 +568,17 @@ if !mongoid? && active_record4?
|
|
|
515
568
|
end
|
|
516
569
|
end
|
|
517
570
|
|
|
571
|
+
describe Bullet::Detector::Association, "has_one => has_many" do
|
|
572
|
+
it "should not detect preload association" do
|
|
573
|
+
user = User.first
|
|
574
|
+
user.submission.replies.map(&:name)
|
|
575
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
576
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
577
|
+
|
|
578
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
|
|
518
582
|
describe Bullet::Detector::Association, "call one association that in possible objects" do
|
|
519
583
|
it "should not detect preload association" do
|
|
520
584
|
Post.all
|
|
@@ -526,6 +590,50 @@ if !mongoid? && active_record4?
|
|
|
526
590
|
end
|
|
527
591
|
end
|
|
528
592
|
|
|
593
|
+
describe Bullet::Detector::Association, "query immediately after creation" do
|
|
594
|
+
context "with save" do
|
|
595
|
+
context "document => children" do
|
|
596
|
+
it 'should not detect non preload associations' do
|
|
597
|
+
document1 = Document.new
|
|
598
|
+
document1.children.build
|
|
599
|
+
document1.save
|
|
600
|
+
|
|
601
|
+
document2 = Document.new(parent: document1)
|
|
602
|
+
document2.save
|
|
603
|
+
document2.parent
|
|
604
|
+
|
|
605
|
+
document1.children.each.first
|
|
606
|
+
|
|
607
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
608
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
609
|
+
|
|
610
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
context "with save!" do
|
|
616
|
+
context "document => children" do
|
|
617
|
+
it 'should not detect non preload associations' do
|
|
618
|
+
document1 = Document.new
|
|
619
|
+
document1.children.build
|
|
620
|
+
document1.save!
|
|
621
|
+
|
|
622
|
+
document2 = Document.new(parent: document1)
|
|
623
|
+
document2.save!
|
|
624
|
+
document2.parent
|
|
625
|
+
|
|
626
|
+
document1.children.each.first
|
|
627
|
+
|
|
628
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
629
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
630
|
+
|
|
631
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
end
|
|
635
|
+
end
|
|
636
|
+
|
|
529
637
|
describe Bullet::Detector::Association, "STI" do
|
|
530
638
|
context "page => author" do
|
|
531
639
|
it "should detect non preload associations" do
|
|
@@ -613,7 +721,7 @@ if !mongoid? && active_record4?
|
|
|
613
721
|
|
|
614
722
|
context "whitelist n plus one query" do
|
|
615
723
|
before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
|
|
616
|
-
after { Bullet.
|
|
724
|
+
after { Bullet.clear_whitelist }
|
|
617
725
|
|
|
618
726
|
it "should not detect n plus one query" do
|
|
619
727
|
Post.all.each do |post|
|
|
@@ -636,7 +744,7 @@ if !mongoid? && active_record4?
|
|
|
636
744
|
|
|
637
745
|
context "whitelist unused eager loading" do
|
|
638
746
|
before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
|
|
639
|
-
after { Bullet.
|
|
747
|
+
after { Bullet.clear_whitelist }
|
|
640
748
|
|
|
641
749
|
it "should not detect unused eager loading" do
|
|
642
750
|
Post.includes(:comments).map(&:name)
|