bullet_instructure 4.0.5 → 4.14.7
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 +27 -1
- data/CHANGELOG.md +44 -2
- data/Gemfile.mongoid +0 -2
- data/Gemfile.mongoid-2.4 +2 -4
- data/Gemfile.mongoid-2.5 +2 -4
- data/Gemfile.mongoid-2.6 +1 -3
- data/Gemfile.mongoid-2.7 +2 -4
- data/Gemfile.mongoid-2.8 +2 -4
- data/Gemfile.mongoid-3.0 +2 -4
- data/Gemfile.mongoid-3.1 +2 -4
- data/Gemfile.mongoid-4.0 +2 -4
- data/Gemfile.rails-3.0 +1 -3
- data/Gemfile.rails-3.1 +1 -3
- data/Gemfile.rails-3.2 +1 -3
- data/Gemfile.rails-4.0 +1 -3
- data/Gemfile.rails-4.1 +1 -3
- data/Gemfile.rails-4.2 +17 -0
- data/README.md +55 -43
- data/bullet_instructure.gemspec +2 -1
- data/lib/bullet/active_record3.rb +68 -34
- data/lib/bullet/active_record3x.rb +60 -32
- data/lib/bullet/active_record4.rb +57 -39
- data/lib/bullet/active_record41.rb +83 -42
- data/lib/bullet/active_record42.rb +195 -0
- data/lib/bullet/dependency.rb +6 -0
- data/lib/bullet/detector/association.rb +23 -17
- data/lib/bullet/detector/counter_cache.rb +16 -16
- data/lib/bullet/detector/n_plus_one_query.rb +43 -30
- data/lib/bullet/detector/unused_eager_loading.rb +2 -2
- data/lib/bullet/ext/object.rb +6 -2
- data/lib/bullet/notification/base.rb +17 -18
- data/lib/bullet/notification/n_plus_one_query.rb +6 -4
- data/lib/bullet/notification/unused_eager_loading.rb +1 -1
- data/lib/bullet/rack.rb +21 -14
- data/lib/bullet/version.rb +2 -2
- data/lib/bullet.rb +18 -10
- data/spec/bullet/detector/counter_cache_spec.rb +8 -8
- data/spec/bullet/detector/n_plus_one_query_spec.rb +27 -27
- data/spec/bullet/ext/object_spec.rb +14 -0
- data/spec/bullet/notification/base_spec.rb +30 -18
- data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +1 -1
- data/spec/bullet/rack_spec.rb +3 -3
- data/spec/bullet_spec.rb +2 -2
- data/spec/integration/active_record3/association_spec.rb +22 -2
- data/spec/integration/active_record4/association_spec.rb +47 -2
- data/spec/models/category.rb +5 -2
- data/spec/models/comment.rb +2 -0
- data/spec/models/post.rb +8 -3
- data/spec/models/reply.rb +3 -0
- data/spec/models/submission.rb +1 -1
- data/spec/spec_helper.rb +4 -4
- data/spec/support/sqlite_seed.rb +14 -6
- data/test.sh +1 -0
- data/update.sh +14 -0
- metadata +26 -9
- data/.ruby-version +0 -1
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'redcarpet'
|
2
|
+
|
1
3
|
module Bullet
|
2
4
|
module Notification
|
3
5
|
class Base
|
@@ -18,25 +20,21 @@ module Bullet
|
|
18
20
|
raise NoMethodError.new("no method body defined")
|
19
21
|
end
|
20
22
|
|
23
|
+
def call_stack_messages
|
24
|
+
""
|
25
|
+
end
|
26
|
+
|
21
27
|
def whoami
|
22
|
-
user
|
23
|
-
if user
|
24
|
-
"user: #{user
|
28
|
+
@user ||= ENV['USER'].presence || (`whoami`.chomp rescue "")
|
29
|
+
if @user.present?
|
30
|
+
"user: #{@user}"
|
25
31
|
else
|
26
32
|
""
|
27
33
|
end
|
28
34
|
end
|
29
35
|
|
30
36
|
def body_with_caller
|
31
|
-
body
|
32
|
-
end
|
33
|
-
|
34
|
-
def standard_notice
|
35
|
-
@standard_notifice ||= title + "\n" + body
|
36
|
-
end
|
37
|
-
|
38
|
-
def full_notice
|
39
|
-
[url, title, body_with_caller].compact.join("\n")
|
37
|
+
"#{body}\n#{call_stack_messages}\n"
|
40
38
|
end
|
41
39
|
|
42
40
|
def notify_inline
|
@@ -48,11 +46,12 @@ module Bullet
|
|
48
46
|
end
|
49
47
|
|
50
48
|
def short_notice
|
51
|
-
[url, title, body].compact.join("
|
49
|
+
[whoami.presence, url, title, body].compact.join(" ")
|
52
50
|
end
|
53
51
|
|
54
52
|
def notification_data
|
55
53
|
{
|
54
|
+
:user => whoami,
|
56
55
|
:url => url,
|
57
56
|
:title => title,
|
58
57
|
:body => body_with_caller,
|
@@ -66,7 +65,7 @@ module Bullet
|
|
66
65
|
def hash
|
67
66
|
klazz_associations_str.hash
|
68
67
|
end
|
69
|
-
|
68
|
+
|
70
69
|
class HTMLwithPygments < Redcarpet::Render::HTML
|
71
70
|
def block_code(code, language)
|
72
71
|
Pygments.highlight(code, :lexer => language)
|
@@ -75,20 +74,20 @@ module Bullet
|
|
75
74
|
|
76
75
|
def markdown(text)
|
77
76
|
renderer = HTMLwithPygments.new(hard_wrap: true)
|
78
|
-
|
77
|
+
options = {
|
79
78
|
:no_intra_emphasis => true,
|
80
79
|
:fenced_code_blocks => true
|
81
|
-
|
80
|
+
}
|
82
81
|
Redcarpet::Markdown.new(renderer, options).render(text).html_safe
|
83
82
|
end
|
84
|
-
|
83
|
+
|
85
84
|
protected
|
86
85
|
def klazz_associations_str
|
87
86
|
" #{@base_class} => [#{@associations.map(&:inspect).join(', ')}]"
|
88
87
|
end
|
89
88
|
|
90
89
|
def associations_str
|
91
|
-
":
|
90
|
+
":includes => #{@associations.map{ |a| a.to_s.to_sym unless a.is_a? Hash }.inspect}"
|
92
91
|
end
|
93
92
|
end
|
94
93
|
end
|
@@ -7,10 +7,6 @@ module Bullet
|
|
7
7
|
@callers = callers
|
8
8
|
end
|
9
9
|
|
10
|
-
def body_with_caller
|
11
|
-
markdown("#{body}\n#{call_stack_messages}")
|
12
|
-
end
|
13
|
-
|
14
10
|
def body
|
15
11
|
"#{klazz_associations_str}\n Add to your finder: #{associations_str}"
|
16
12
|
end
|
@@ -19,6 +15,12 @@ module Bullet
|
|
19
15
|
markdown(("##")+"N+1 Query #{@path ? "in #{@path}" : 'detected'}")
|
20
16
|
end
|
21
17
|
|
18
|
+
def notification_data
|
19
|
+
super.merge(
|
20
|
+
:backtrace => @callers
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
22
24
|
protected
|
23
25
|
def call_stack_messages
|
24
26
|
markdown((['N+1 Query method call stack'] + @callers).join( "\n " ))
|
data/lib/bullet/rack.rb
CHANGED
@@ -10,21 +10,20 @@ module Bullet
|
|
10
10
|
return @app.call(env) unless Bullet.enable?
|
11
11
|
Bullet.start_request
|
12
12
|
status, headers, response = @app.call(env)
|
13
|
-
return [status, headers, response] if file?(headers) || sse?(response) || empty?(response)
|
14
13
|
|
15
14
|
response_body = nil
|
16
15
|
if Bullet.notification?
|
17
|
-
if
|
18
|
-
|
19
|
-
|
16
|
+
if !file?(headers) && !sse?(headers) && !empty?(response) &&
|
17
|
+
status == 200 && !response_body(response).frozen? && html_request?(headers, response)
|
18
|
+
response_body = response_body(response)
|
19
|
+
append_to_html_body(response_body, footer_note) if Bullet.add_footer
|
20
|
+
append_to_html_body(response_body, Bullet.gather_inline_notifications)
|
20
21
|
headers['Content-Length'] = response_body.bytesize.to_s
|
21
22
|
end
|
23
|
+
Bullet.perform_out_of_channel_notifications(env)
|
22
24
|
end
|
23
25
|
[status, headers, response_body ? [response_body] : response]
|
24
26
|
ensure
|
25
|
-
if Bullet.enable? && Bullet.notification?
|
26
|
-
Bullet.perform_out_of_channel_notifications(env)
|
27
|
-
end
|
28
27
|
Bullet.end_request
|
29
28
|
end
|
30
29
|
|
@@ -42,16 +41,25 @@ module Bullet
|
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
|
-
def
|
46
|
-
response_body
|
44
|
+
def append_to_html_body(response_body, content)
|
45
|
+
if response_body.include?('</body>')
|
46
|
+
position = response_body.rindex('</body>')
|
47
|
+
response_body.insert(position, content)
|
48
|
+
else
|
49
|
+
response_body << content
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def footer_note
|
54
|
+
"<div #{footer_div_attributes}>" + Bullet.footer_info.uniq.join("<br>") + "</div>"
|
47
55
|
end
|
48
56
|
|
49
57
|
def file?(headers)
|
50
58
|
headers["Content-Transfer-Encoding"] == "binary"
|
51
59
|
end
|
52
60
|
|
53
|
-
def sse?(
|
54
|
-
|
61
|
+
def sse?(headers)
|
62
|
+
headers["Content-Type"] == "text/event-stream"
|
55
63
|
end
|
56
64
|
|
57
65
|
def html_request?(headers, response)
|
@@ -67,9 +75,9 @@ module Bullet
|
|
67
75
|
end
|
68
76
|
|
69
77
|
private
|
70
|
-
def
|
78
|
+
def footer_div_attributes
|
71
79
|
<<EOF
|
72
|
-
style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: solid; border-color: rgb(153, 153, 153);
|
80
|
+
data-is-bullet-footer ondblclick="this.parentNode.removeChild(this);" style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: solid; border-color: rgb(153, 153, 153);
|
73
81
|
-moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none;
|
74
82
|
-moz-border-left-colors: none; -moz-border-image: none; border-width: 2pt 2pt 0px 0px;
|
75
83
|
padding: 5px; border-radius: 0pt 10pt 0pt 0px; background: none repeat scroll 0% 0% rgba(200, 200, 200, 0.8);
|
@@ -78,4 +86,3 @@ EOF
|
|
78
86
|
end
|
79
87
|
end
|
80
88
|
end
|
81
|
-
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
@@ -29,7 +29,9 @@ module Bullet
|
|
29
29
|
attr_reader :notification_collector, :whitelist
|
30
30
|
attr_accessor :add_footer, :orm_pathches_applied
|
31
31
|
|
32
|
-
|
32
|
+
available_notifiers = UniformNotifier::AVAILABLE_NOTIFIERS.map { |notifier| "#{notifier}=" }
|
33
|
+
available_notifiers << { :to => UniformNotifier }
|
34
|
+
delegate *available_notifiers
|
33
35
|
|
34
36
|
def raise=(should_raise)
|
35
37
|
UniformNotifier.raise=(should_raise ? Notification::UnoptimizedQueryError : false)
|
@@ -96,7 +98,7 @@ module Bullet
|
|
96
98
|
end
|
97
99
|
|
98
100
|
def debug(title, message)
|
99
|
-
puts "[Bullet][#{title}] #{message}" if ENV['
|
101
|
+
puts "[Bullet][#{title}] #{message}" if ENV['BULLET_DEBUG'] == 'true'
|
100
102
|
end
|
101
103
|
|
102
104
|
def start_request
|
@@ -107,6 +109,7 @@ module Bullet
|
|
107
109
|
Thread.current[:bullet_call_object_associations] = Bullet::Registry::Base.new
|
108
110
|
Thread.current[:bullet_possible_objects] = Bullet::Registry::Object.new
|
109
111
|
Thread.current[:bullet_impossible_objects] = Bullet::Registry::Object.new
|
112
|
+
Thread.current[:bullet_inversed_objects] = Bullet::Registry::Base.new
|
110
113
|
Thread.current[:bullet_eager_loadings] = Bullet::Registry::Association.new
|
111
114
|
|
112
115
|
Thread.current[:bullet_counter_possible_objects] ||= Bullet::Registry::Object.new
|
@@ -118,9 +121,10 @@ module Bullet
|
|
118
121
|
Thread.current[:bullet_notification_collector] = nil
|
119
122
|
|
120
123
|
Thread.current[:bullet_object_associations] = nil
|
124
|
+
Thread.current[:bullet_call_object_associations] = nil
|
121
125
|
Thread.current[:bullet_possible_objects] = nil
|
122
126
|
Thread.current[:bullet_impossible_objects] = nil
|
123
|
-
Thread.current[:
|
127
|
+
Thread.current[:bullet_inversed_objects] = nil
|
124
128
|
Thread.current[:bullet_eager_loadings] = nil
|
125
129
|
|
126
130
|
Thread.current[:bullet_counter_possible_objects] = nil
|
@@ -136,6 +140,7 @@ module Bullet
|
|
136
140
|
end
|
137
141
|
|
138
142
|
def notification?
|
143
|
+
return unless start?
|
139
144
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
140
145
|
notification_collector.notifications_present?
|
141
146
|
end
|
@@ -150,14 +155,14 @@ module Bullet
|
|
150
155
|
|
151
156
|
def perform_out_of_channel_notifications(env = {})
|
152
157
|
for_each_active_notifier_with_notification do |notification|
|
153
|
-
notification.url =
|
158
|
+
notification.url = env['REQUEST_URI']
|
154
159
|
notification.notify_out_of_channel
|
155
160
|
end
|
156
161
|
end
|
157
162
|
|
158
163
|
def footer_info
|
159
164
|
info = []
|
160
|
-
|
165
|
+
notification_collector.collection.each do |notification|
|
161
166
|
info << notification.short_notice
|
162
167
|
end
|
163
168
|
info
|
@@ -173,14 +178,17 @@ module Bullet
|
|
173
178
|
end
|
174
179
|
|
175
180
|
def profile
|
176
|
-
|
181
|
+
if Bullet.enable?
|
182
|
+
begin
|
183
|
+
Bullet.start_request
|
177
184
|
|
178
|
-
|
185
|
+
yield
|
179
186
|
|
180
|
-
|
181
|
-
|
187
|
+
Bullet.perform_out_of_channel_notifications if Bullet.notification?
|
188
|
+
ensure
|
189
|
+
Bullet.end_request
|
190
|
+
end
|
182
191
|
end
|
183
|
-
Bullet.end_request if Bullet.enable?
|
184
192
|
end
|
185
193
|
|
186
194
|
private
|
@@ -10,13 +10,13 @@ module Bullet
|
|
10
10
|
|
11
11
|
context ".add_counter_cache" do
|
12
12
|
it "should create notification if conditions met" do
|
13
|
-
expect(CounterCache).to receive(:conditions_met?).with(@post1
|
13
|
+
expect(CounterCache).to receive(:conditions_met?).with(@post1, [:comments]).and_return(true)
|
14
14
|
expect(CounterCache).to receive(:create_notification).with("Post", [:comments])
|
15
15
|
CounterCache.add_counter_cache(@post1, [:comments])
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should not create notification if conditions not met" do
|
19
|
-
expect(CounterCache).to receive(:conditions_met?).with(@post1
|
19
|
+
expect(CounterCache).to receive(:conditions_met?).with(@post1, [:comments]).and_return(false)
|
20
20
|
expect(CounterCache).to receive(:create_notification).never
|
21
21
|
CounterCache.add_counter_cache(@post1, [:comments])
|
22
22
|
end
|
@@ -25,30 +25,30 @@ module Bullet
|
|
25
25
|
context ".add_possible_objects" do
|
26
26
|
it "should add possible objects" do
|
27
27
|
CounterCache.add_possible_objects([@post1, @post2])
|
28
|
-
expect(CounterCache.
|
29
|
-
expect(CounterCache.
|
28
|
+
expect(CounterCache.possible_objects).to be_include(@post1.bullet_key)
|
29
|
+
expect(CounterCache.possible_objects).to be_include(@post2.bullet_key)
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should add impossible object" do
|
33
33
|
CounterCache.add_impossible_object(@post1)
|
34
|
-
expect(CounterCache.
|
34
|
+
expect(CounterCache.impossible_objects).to be_include(@post1.bullet_key)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
context ".conditions_met?" do
|
39
39
|
it "should be true when object is possible, not impossible" do
|
40
40
|
CounterCache.add_possible_objects(@post1)
|
41
|
-
expect(CounterCache.
|
41
|
+
expect(CounterCache.conditions_met?(@post1, :associations)).to eq true
|
42
42
|
end
|
43
43
|
|
44
44
|
it "should be false when object is not possible" do
|
45
|
-
expect(CounterCache.
|
45
|
+
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should be true when object is possible, and impossible" do
|
49
49
|
CounterCache.add_possible_objects(@post1)
|
50
50
|
CounterCache.add_impossible_object(@post1)
|
51
|
-
expect(CounterCache.
|
51
|
+
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -18,69 +18,69 @@ module Bullet
|
|
18
18
|
context ".possible?" do
|
19
19
|
it "should be true if possible_objects contain" do
|
20
20
|
NPlusOneQuery.add_possible_objects(@post)
|
21
|
-
expect(NPlusOneQuery.
|
21
|
+
expect(NPlusOneQuery.possible?(@post)).to eq true
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
context ".impossible?" do
|
26
26
|
it "should be true if impossible_objects contain" do
|
27
27
|
NPlusOneQuery.add_impossible_object(@post)
|
28
|
-
expect(NPlusOneQuery.
|
28
|
+
expect(NPlusOneQuery.impossible?(@post)).to eq true
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
context ".association?" do
|
33
33
|
it "should be true if object, associations pair is already existed" do
|
34
34
|
NPlusOneQuery.add_object_associations(@post, :association)
|
35
|
-
expect(NPlusOneQuery.
|
35
|
+
expect(NPlusOneQuery.association?(@post, :association)).to eq true
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should be false if object, association pair is not existed" do
|
39
39
|
NPlusOneQuery.add_object_associations(@post, :association1)
|
40
|
-
expect(NPlusOneQuery.
|
40
|
+
expect(NPlusOneQuery.association?(@post, :associatio2)).to eq false
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
context ".conditions_met?" do
|
45
45
|
it "should be true if object is possible, not impossible and object, associations pair is not already existed" do
|
46
|
-
allow(NPlusOneQuery).to receive(:possible?).with(@post
|
47
|
-
allow(NPlusOneQuery).to receive(:impossible?).with(@post
|
48
|
-
allow(NPlusOneQuery).to receive(:association?).with(@post
|
49
|
-
expect(NPlusOneQuery.
|
46
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
47
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
48
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
49
|
+
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq true
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should be false if object is not possible, not impossible and object, associations pair is not already existed" do
|
53
|
-
allow(NPlusOneQuery).to receive(:possible?).with(@post
|
54
|
-
allow(NPlusOneQuery).to receive(:impossible?).with(@post
|
55
|
-
allow(NPlusOneQuery).to receive(:association?).with(@post
|
56
|
-
expect(NPlusOneQuery.
|
53
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(false)
|
54
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
55
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
56
|
+
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should be false if object is possible, but impossible and object, associations pair is not already existed" do
|
60
|
-
allow(NPlusOneQuery).to receive(:possible?).with(@post
|
61
|
-
allow(NPlusOneQuery).to receive(:impossible?).with(@post
|
62
|
-
allow(NPlusOneQuery).to receive(:association?).with(@post
|
63
|
-
expect(NPlusOneQuery.
|
60
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
61
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(true)
|
62
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
63
|
+
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
|
64
64
|
end
|
65
65
|
|
66
66
|
it "should be false if object is possible, not impossible and object, associations pair is already existed" do
|
67
|
-
allow(NPlusOneQuery).to receive(:possible?).with(@post
|
68
|
-
allow(NPlusOneQuery).to receive(:impossible?).with(@post
|
69
|
-
allow(NPlusOneQuery).to receive(:association?).with(@post
|
70
|
-
expect(NPlusOneQuery.
|
67
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
68
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
69
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(true)
|
70
|
+
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
74
|
context ".call_association" do
|
75
75
|
it "should create notification if conditions met" do
|
76
|
-
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post
|
76
|
+
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
77
77
|
expect(NPlusOneQuery).to receive(:caller_in_project).and_return(["caller"])
|
78
78
|
expect(NPlusOneQuery).to receive(:create_notification).with(["caller"], "Post", :association)
|
79
79
|
NPlusOneQuery.call_association(@post, :association)
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should not create notification if conditions not met" do
|
83
|
-
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post
|
83
|
+
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(false)
|
84
84
|
expect(NPlusOneQuery).not_to receive(:caller_in_project!)
|
85
85
|
expect(NPlusOneQuery).not_to receive(:create_notification).with("Post", :association)
|
86
86
|
NPlusOneQuery.call_association(@post, :association)
|
@@ -93,7 +93,7 @@ module Bullet
|
|
93
93
|
not_in_project = '/def/def.rb'
|
94
94
|
|
95
95
|
expect(NPlusOneQuery).to receive(:caller).and_return([in_project, not_in_project])
|
96
|
-
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post
|
96
|
+
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
97
97
|
expect(NPlusOneQuery).to receive(:create_notification).with([in_project], "Post", :association)
|
98
98
|
NPlusOneQuery.call_association(@post, :association)
|
99
99
|
end
|
@@ -108,7 +108,7 @@ module Bullet
|
|
108
108
|
excluded_gem = '/ghi/ghi.rb'
|
109
109
|
|
110
110
|
expect(NPlusOneQuery).to receive(:caller).and_return([in_project, included_gem, excluded_gem])
|
111
|
-
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post
|
111
|
+
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
112
112
|
expect(NPlusOneQuery).to receive(:create_notification).with([in_project, included_gem], "Post", :association)
|
113
113
|
NPlusOneQuery.call_association(@post, :association)
|
114
114
|
end
|
@@ -118,8 +118,8 @@ module Bullet
|
|
118
118
|
context ".add_possible_objects" do
|
119
119
|
it "should add possible objects" do
|
120
120
|
NPlusOneQuery.add_possible_objects([@post, @post2])
|
121
|
-
expect(NPlusOneQuery.
|
122
|
-
expect(NPlusOneQuery.
|
121
|
+
expect(NPlusOneQuery.possible_objects).to be_include(@post.bullet_key)
|
122
|
+
expect(NPlusOneQuery.possible_objects).to be_include(@post2.bullet_key)
|
123
123
|
end
|
124
124
|
|
125
125
|
it "should not raise error if object is nil" do
|
@@ -130,7 +130,7 @@ module Bullet
|
|
130
130
|
context ".add_impossible_object" do
|
131
131
|
it "should add impossible object" do
|
132
132
|
NPlusOneQuery.add_impossible_object(@post)
|
133
|
-
expect(NPlusOneQuery.
|
133
|
+
expect(NPlusOneQuery.impossible_objects).to be_include(@post.bullet_key)
|
134
134
|
end
|
135
135
|
end
|
136
136
|
end
|
@@ -14,4 +14,18 @@ describe Object do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
context "primary_key_value" do
|
19
|
+
it "should return id" do
|
20
|
+
post = Post.first
|
21
|
+
expect(post.primary_key_value).to eq(post.id)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return primary key value" do
|
25
|
+
post = Post.first
|
26
|
+
Post.primary_key = 'name'
|
27
|
+
expect(post.primary_key_value).to eq(post.name)
|
28
|
+
Post.primary_key = 'id'
|
29
|
+
end
|
30
|
+
end
|
17
31
|
end
|
@@ -22,30 +22,42 @@ module Bullet
|
|
22
22
|
user = `whoami`.chomp
|
23
23
|
expect(subject.whoami).to eq("user: #{user}")
|
24
24
|
end
|
25
|
-
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
it "should leverage ENV parameter" do
|
27
|
+
temp_env_variable("USER", "bogus") do
|
28
|
+
expect(subject.whoami).to eq("user: bogus")
|
29
|
+
end
|
31
30
|
end
|
32
|
-
end
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
it "should return blank if no user available" do
|
33
|
+
temp_env_variable("USER","") do
|
34
|
+
expect(subject).to receive(:`).with("whoami").and_return("")
|
35
|
+
expect(subject.whoami).to eq("")
|
36
|
+
end
|
39
37
|
end
|
38
|
+
|
39
|
+
it "should return blank if whoami is not available" do
|
40
|
+
temp_env_variable("USER","") do
|
41
|
+
expect(subject).to receive(:`).with("whoami").and_raise(Errno::ENOENT)
|
42
|
+
expect(subject.whoami).to eq("")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def temp_env_variable(name, value)
|
47
|
+
old_value = ENV[name]
|
48
|
+
ENV[name] = value
|
49
|
+
yield
|
50
|
+
ensure
|
51
|
+
ENV[name] = old_value
|
52
|
+
end
|
53
|
+
|
40
54
|
end
|
41
55
|
|
42
|
-
context "#
|
43
|
-
it "should return
|
44
|
-
allow(subject).to receive(:
|
45
|
-
allow(subject).to receive(:
|
46
|
-
|
47
|
-
allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
|
48
|
-
expect(subject.full_notice).to eq("whoami\nurl\ntitle\nbody_with_caller")
|
56
|
+
context "#body_with_caller" do
|
57
|
+
it "should return body" do
|
58
|
+
allow(subject).to receive(:body).and_return("body")
|
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")
|
49
61
|
end
|
50
62
|
end
|
51
63
|
|
@@ -5,9 +5,9 @@ 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: :
|
8
|
+
it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call 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]\nN+1 Query method call stack\n caller1\n caller2\n", " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call 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
11
|
it { expect(subject.title).to eq("N+1 Query in path") }
|
12
12
|
end
|
13
13
|
end
|
@@ -5,7 +5,7 @@ module Bullet
|
|
5
5
|
describe UnusedEagerLoading do
|
6
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: :
|
8
|
+
it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :includes => [:comments, :votes]") }
|
9
9
|
it { expect(subject.title).to eq("Unused Eager Loading in path") }
|
10
10
|
end
|
11
11
|
end
|
data/spec/bullet/rack_spec.rb
CHANGED
@@ -65,19 +65,19 @@ module Bullet
|
|
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
71
|
status, headers, response = middleware.call([200, {"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
82
|
status, headers, response = middleware.call([200, {"Content-Type" => "text/html"}])
|
83
83
|
expect(headers["Content-Length"]).to eq("58")
|
data/spec/bullet_spec.rb
CHANGED
@@ -26,8 +26,8 @@ describe Bullet, focused: true do
|
|
26
26
|
|
27
27
|
context 'enable Bullet again without patching again the orms' do
|
28
28
|
before do
|
29
|
-
Bullet::Mongoid.
|
30
|
-
Bullet::ActiveRecord.
|
29
|
+
expect(Bullet::Mongoid).not_to receive(:enable) if defined? Bullet::Mongoid
|
30
|
+
expect(Bullet::ActiveRecord).not_to receive(:enable) if defined? Bullet::ActiveRecord
|
31
31
|
Bullet.enable = true
|
32
32
|
end
|
33
33
|
|