bullet 5.9.0 → 6.1.1
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 +5 -5
- data/.travis.yml +22 -1
- data/CHANGELOG.md +27 -0
- data/Gemfile.rails-4.0 +1 -1
- data/Gemfile.rails-4.1 +1 -1
- data/Gemfile.rails-4.2 +1 -1
- data/Gemfile.rails-5.0 +1 -1
- data/Gemfile.rails-5.1 +1 -1
- data/Gemfile.rails-5.2 +1 -1
- data/Gemfile.rails-6.0 +15 -0
- data/Gemfile.rails-6.1 +15 -0
- data/README.md +31 -10
- data/lib/bullet.rb +50 -26
- data/lib/bullet/active_job.rb +13 -0
- data/lib/bullet/active_record4.rb +9 -32
- data/lib/bullet/active_record41.rb +7 -27
- data/lib/bullet/active_record42.rb +8 -24
- data/lib/bullet/active_record5.rb +188 -179
- data/lib/bullet/active_record52.rb +176 -168
- data/lib/bullet/active_record60.rb +267 -0
- data/lib/bullet/active_record61.rb +267 -0
- data/lib/bullet/bullet_xhr.js +63 -0
- data/lib/bullet/dependency.rb +50 -36
- data/lib/bullet/detector/association.rb +26 -20
- data/lib/bullet/detector/base.rb +1 -2
- data/lib/bullet/detector/counter_cache.rb +13 -9
- data/lib/bullet/detector/n_plus_one_query.rb +22 -12
- data/lib/bullet/detector/unused_eager_loading.rb +6 -3
- data/lib/bullet/ext/object.rb +4 -2
- data/lib/bullet/mongoid4x.rb +2 -6
- data/lib/bullet/mongoid5x.rb +2 -6
- data/lib/bullet/mongoid6x.rb +2 -6
- data/lib/bullet/mongoid7x.rb +2 -6
- 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 +50 -25
- data/lib/bullet/stack_trace_filter.rb +6 -12
- 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/ext/object_spec.rb +9 -4
- 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 +86 -6
- data/spec/bullet/registry/association_spec.rb +2 -2
- data/spec/bullet/registry/base_spec.rb +1 -1
- data/spec/bullet_spec.rb +11 -30
- data/spec/integration/active_record/association_spec.rb +44 -136
- data/spec/integration/counter_cache_spec.rb +11 -31
- data/spec/integration/mongoid/association_spec.rb +18 -32
- data/spec/models/folder.rb +1 -2
- data/spec/models/group.rb +1 -2
- data/spec/models/page.rb +1 -2
- 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/test.sh +1 -0
- metadata +12 -7
data/lib/bullet/detector/base.rb
CHANGED
@@ -3,16 +3,17 @@
|
|
3
3
|
module Bullet
|
4
4
|
module Detector
|
5
5
|
class CounterCache < Base
|
6
|
-
class <<self
|
6
|
+
class << self
|
7
7
|
def add_counter_cache(object, associations)
|
8
8
|
return unless Bullet.start?
|
9
9
|
return unless Bullet.counter_cache_enable?
|
10
|
-
return unless object.
|
10
|
+
return unless object.bullet_primary_key_value
|
11
11
|
|
12
|
-
Bullet.debug(
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
Bullet.debug(
|
13
|
+
'Detector::CounterCache#add_counter_cache',
|
14
|
+
"object: #{object.bullet_key}, associations: #{associations}"
|
15
|
+
)
|
16
|
+
create_notification object.class.to_s, associations if conditions_met?(object, associations)
|
16
17
|
end
|
17
18
|
|
18
19
|
def add_possible_objects(object_or_objects)
|
@@ -20,16 +21,19 @@ module Bullet
|
|
20
21
|
return unless Bullet.counter_cache_enable?
|
21
22
|
|
22
23
|
objects = Array(object_or_objects)
|
23
|
-
return if objects.map(&:
|
24
|
+
return if objects.map(&:bullet_primary_key_value).compact.empty?
|
24
25
|
|
25
|
-
Bullet.debug(
|
26
|
+
Bullet.debug(
|
27
|
+
'Detector::CounterCache#add_possible_objects',
|
28
|
+
"objects: #{objects.map(&:bullet_key).join(', ')}"
|
29
|
+
)
|
26
30
|
objects.each { |object| possible_objects.add object.bullet_key }
|
27
31
|
end
|
28
32
|
|
29
33
|
def add_impossible_object(object)
|
30
34
|
return unless Bullet.start?
|
31
35
|
return unless Bullet.counter_cache_enable?
|
32
|
-
return unless object.
|
36
|
+
return unless object.bullet_primary_key_value
|
33
37
|
|
34
38
|
Bullet.debug('Detector::CounterCache#add_impossible_object', "object: #{object.bullet_key}")
|
35
39
|
impossible_objects.add object.bullet_key
|
@@ -6,7 +6,7 @@ module Bullet
|
|
6
6
|
extend Dependency
|
7
7
|
extend StackTraceFilter
|
8
8
|
|
9
|
-
class <<self
|
9
|
+
class << self
|
10
10
|
# executed when object.assocations is called.
|
11
11
|
# first, it keeps this method call for object.association.
|
12
12
|
# then, it checks if this associations call is unpreload.
|
@@ -14,12 +14,15 @@ module Bullet
|
|
14
14
|
def call_association(object, associations)
|
15
15
|
return unless Bullet.start?
|
16
16
|
return unless Bullet.n_plus_one_query_enable?
|
17
|
-
return unless object.
|
17
|
+
return unless object.bullet_primary_key_value
|
18
18
|
return if inversed_objects.include?(object.bullet_key, associations)
|
19
19
|
|
20
20
|
add_call_object_associations(object, associations)
|
21
21
|
|
22
|
-
Bullet.debug(
|
22
|
+
Bullet.debug(
|
23
|
+
'Detector::NPlusOneQuery#call_association',
|
24
|
+
"object: #{object.bullet_key}, associations: #{associations}"
|
25
|
+
)
|
23
26
|
if !excluded_stacktrace_path? && conditions_met?(object, associations)
|
24
27
|
Bullet.debug('detect n + 1 query', "object: #{object.bullet_key}, associations: #{associations}")
|
25
28
|
create_notification caller_in_project, object.class.to_s, associations
|
@@ -31,16 +34,19 @@ module Bullet
|
|
31
34
|
return unless Bullet.n_plus_one_query_enable?
|
32
35
|
|
33
36
|
objects = Array(object_or_objects)
|
34
|
-
return if objects.map(&:
|
37
|
+
return if objects.map(&:bullet_primary_key_value).compact.empty?
|
35
38
|
|
36
|
-
Bullet.debug(
|
39
|
+
Bullet.debug(
|
40
|
+
'Detector::NPlusOneQuery#add_possible_objects',
|
41
|
+
"objects: #{objects.map(&:bullet_key).join(', ')}"
|
42
|
+
)
|
37
43
|
objects.each { |object| possible_objects.add object.bullet_key }
|
38
44
|
end
|
39
45
|
|
40
46
|
def add_impossible_object(object)
|
41
47
|
return unless Bullet.start?
|
42
48
|
return unless Bullet.n_plus_one_query_enable?
|
43
|
-
return unless object.
|
49
|
+
return unless object.bullet_primary_key_value
|
44
50
|
|
45
51
|
Bullet.debug('Detector::NPlusOneQuery#add_impossible_object', "object: #{object.bullet_key}")
|
46
52
|
impossible_objects.add object.bullet_key
|
@@ -49,9 +55,12 @@ module Bullet
|
|
49
55
|
def add_inversed_object(object, association)
|
50
56
|
return unless Bullet.start?
|
51
57
|
return unless Bullet.n_plus_one_query_enable?
|
52
|
-
return unless object.
|
58
|
+
return unless object.bullet_primary_key_value
|
53
59
|
|
54
|
-
Bullet.debug(
|
60
|
+
Bullet.debug(
|
61
|
+
'Detector::NPlusOneQuery#add_inversed_object',
|
62
|
+
"object: #{object.bullet_key}, association: #{association}"
|
63
|
+
)
|
55
64
|
inversed_objects.add object.bullet_key, association
|
56
65
|
end
|
57
66
|
|
@@ -72,10 +81,11 @@ module Bullet
|
|
72
81
|
def association?(object, associations)
|
73
82
|
value = object_associations[object.bullet_key]
|
74
83
|
value&.each do |v|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
result =
|
84
|
+
# associations == v comparison order is important here because
|
85
|
+
# v variable might be a squeel node where :== method is redefined,
|
86
|
+
# so it does not compare values at all and return unexpected results
|
87
|
+
result =
|
88
|
+
v.is_a?(Hash) ? v.key?(associations) : associations == v
|
79
89
|
return true if result
|
80
90
|
end
|
81
91
|
|
@@ -6,7 +6,7 @@ module Bullet
|
|
6
6
|
extend Dependency
|
7
7
|
extend StackTraceFilter
|
8
8
|
|
9
|
-
class <<self
|
9
|
+
class << self
|
10
10
|
# check if there are unused preload associations.
|
11
11
|
# get related_objects from eager_loadings associated with object and associations
|
12
12
|
# get call_object_association from associations of call_object_associations whose object is in related_objects
|
@@ -27,9 +27,12 @@ module Bullet
|
|
27
27
|
def add_eager_loadings(objects, associations)
|
28
28
|
return unless Bullet.start?
|
29
29
|
return unless Bullet.unused_eager_loading_enable?
|
30
|
-
return if objects.map(&:
|
30
|
+
return if objects.map(&:bullet_primary_key_value).compact.empty?
|
31
31
|
|
32
|
-
Bullet.debug(
|
32
|
+
Bullet.debug(
|
33
|
+
'Detector::UnusedEagerLoading#add_eager_loadings',
|
34
|
+
"objects: #{objects.map(&:bullet_key).join(', ')}, associations: #{associations}"
|
35
|
+
)
|
33
36
|
bullet_keys = objects.map(&:bullet_key)
|
34
37
|
|
35
38
|
to_add = []
|
data/lib/bullet/ext/object.rb
CHANGED
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
class Object
|
4
4
|
def bullet_key
|
5
|
-
"#{self.class}:#{
|
5
|
+
"#{self.class}:#{bullet_primary_key_value}"
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
8
|
+
def bullet_primary_key_value
|
9
|
+
return if respond_to?(:persisted?) && !persisted?
|
10
|
+
|
9
11
|
if self.class.respond_to?(:primary_keys) && self.class.primary_keys
|
10
12
|
self.class.primary_keys.map { |primary_key| send primary_key }.join(',')
|
11
13
|
elsif self.class.respond_to?(:primary_key) && self.class.primary_key
|
data/lib/bullet/mongoid4x.rb
CHANGED
@@ -37,9 +37,7 @@ module Bullet
|
|
37
37
|
|
38
38
|
def eager_load(docs)
|
39
39
|
associations = criteria.inclusions.map(&:name)
|
40
|
-
docs.each
|
41
|
-
Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations)
|
42
|
-
end
|
40
|
+
docs.each { |doc| Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations) }
|
43
41
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
|
44
42
|
origin_eager_load(docs)
|
45
43
|
end
|
@@ -50,9 +48,7 @@ module Bullet
|
|
50
48
|
|
51
49
|
def get_relation(name, metadata, object, reload = false)
|
52
50
|
result = origin_get_relation(name, metadata, object, reload)
|
53
|
-
if metadata.macro !~ /embed/
|
54
|
-
Bullet::Detector::NPlusOneQuery.call_association(self, name)
|
55
|
-
end
|
51
|
+
Bullet::Detector::NPlusOneQuery.call_association(self, name) if metadata.macro !~ /embed/
|
56
52
|
result
|
57
53
|
end
|
58
54
|
end
|
data/lib/bullet/mongoid5x.rb
CHANGED
@@ -37,9 +37,7 @@ module Bullet
|
|
37
37
|
|
38
38
|
def eager_load(docs)
|
39
39
|
associations = criteria.inclusions.map(&:name)
|
40
|
-
docs.each
|
41
|
-
Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations)
|
42
|
-
end
|
40
|
+
docs.each { |doc| Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations) }
|
43
41
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
|
44
42
|
origin_eager_load(docs)
|
45
43
|
end
|
@@ -50,9 +48,7 @@ module Bullet
|
|
50
48
|
|
51
49
|
def get_relation(name, metadata, object, reload = false)
|
52
50
|
result = origin_get_relation(name, metadata, object, reload)
|
53
|
-
if metadata.macro !~ /embed/
|
54
|
-
Bullet::Detector::NPlusOneQuery.call_association(self, name)
|
55
|
-
end
|
51
|
+
Bullet::Detector::NPlusOneQuery.call_association(self, name) if metadata.macro !~ /embed/
|
56
52
|
result
|
57
53
|
end
|
58
54
|
end
|
data/lib/bullet/mongoid6x.rb
CHANGED
@@ -37,9 +37,7 @@ module Bullet
|
|
37
37
|
|
38
38
|
def eager_load(docs)
|
39
39
|
associations = criteria.inclusions.map(&:name)
|
40
|
-
docs.each
|
41
|
-
Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations)
|
42
|
-
end
|
40
|
+
docs.each { |doc| Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations) }
|
43
41
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
|
44
42
|
origin_eager_load(docs)
|
45
43
|
end
|
@@ -50,9 +48,7 @@ module Bullet
|
|
50
48
|
|
51
49
|
def get_relation(name, metadata, object, reload = false)
|
52
50
|
result = origin_get_relation(name, metadata, object, reload)
|
53
|
-
if metadata.macro !~ /embed/
|
54
|
-
Bullet::Detector::NPlusOneQuery.call_association(self, name)
|
55
|
-
end
|
51
|
+
Bullet::Detector::NPlusOneQuery.call_association(self, name) if metadata.macro !~ /embed/
|
56
52
|
result
|
57
53
|
end
|
58
54
|
end
|
data/lib/bullet/mongoid7x.rb
CHANGED
@@ -37,9 +37,7 @@ module Bullet
|
|
37
37
|
|
38
38
|
def eager_load(docs)
|
39
39
|
associations = criteria.inclusions.map(&:name)
|
40
|
-
docs.each
|
41
|
-
Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations)
|
42
|
-
end
|
40
|
+
docs.each { |doc| Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations) }
|
43
41
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
|
44
42
|
origin_eager_load(docs)
|
45
43
|
end
|
@@ -50,9 +48,7 @@ module Bullet
|
|
50
48
|
|
51
49
|
def get_relation(name, association, object, reload = false)
|
52
50
|
result = origin_get_relation(name, association, object, reload)
|
53
|
-
unless association.embedded?
|
54
|
-
Bullet::Detector::NPlusOneQuery.call_association(self, name)
|
55
|
-
end
|
51
|
+
Bullet::Detector::NPlusOneQuery.call_association(self, name) unless association.embedded?
|
56
52
|
result
|
57
53
|
end
|
58
54
|
end
|
@@ -8,7 +8,8 @@ module Bullet
|
|
8
8
|
|
9
9
|
def initialize(base_class, association_or_associations, path = nil)
|
10
10
|
@base_class = base_class
|
11
|
-
@associations =
|
11
|
+
@associations =
|
12
|
+
association_or_associations.is_a?(Array) ? association_or_associations : [association_or_associations]
|
12
13
|
@path = path
|
13
14
|
end
|
14
15
|
|
@@ -25,16 +26,16 @@ module Bullet
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def whoami
|
28
|
-
@user ||=
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
@user ||=
|
30
|
+
ENV['USER'].presence ||
|
31
|
+
(
|
32
|
+
begin
|
33
|
+
`whoami`.chomp
|
34
|
+
rescue StandardError
|
35
|
+
''
|
36
|
+
end
|
37
|
+
)
|
38
|
+
@user.present? ? "user: #{@user}" : ''
|
38
39
|
end
|
39
40
|
|
40
41
|
def body_with_caller
|
@@ -54,12 +55,7 @@ module Bullet
|
|
54
55
|
end
|
55
56
|
|
56
57
|
def notification_data
|
57
|
-
{
|
58
|
-
user: whoami,
|
59
|
-
url: url,
|
60
|
-
title: title,
|
61
|
-
body: body_with_caller
|
62
|
-
}
|
58
|
+
{ user: whoami, url: url, title: title, body: body_with_caller }
|
63
59
|
end
|
64
60
|
|
65
61
|
def eql?(other)
|
@@ -77,7 +73,7 @@ module Bullet
|
|
77
73
|
end
|
78
74
|
|
79
75
|
def associations_str
|
80
|
-
"
|
76
|
+
".includes(#{@associations.map { |a| a.to_s.to_sym }.inspect})"
|
81
77
|
end
|
82
78
|
end
|
83
79
|
end
|
@@ -10,7 +10,7 @@ module Bullet
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def body
|
13
|
-
"#{klazz_associations_str}\n Add to your
|
13
|
+
"#{klazz_associations_str}\n Add to your query: #{associations_str}"
|
14
14
|
end
|
15
15
|
|
16
16
|
def title
|
@@ -18,9 +18,7 @@ module Bullet
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def notification_data
|
21
|
-
super.merge(
|
22
|
-
backtrace: []
|
23
|
-
)
|
21
|
+
super.merge(backtrace: [])
|
24
22
|
end
|
25
23
|
|
26
24
|
protected
|
@@ -10,7 +10,7 @@ module Bullet
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def body
|
13
|
-
"#{klazz_associations_str}\n Remove from your
|
13
|
+
"#{klazz_associations_str}\n Remove from your query: #{associations_str}"
|
14
14
|
end
|
15
15
|
|
16
16
|
def title
|
@@ -18,9 +18,7 @@ module Bullet
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def notification_data
|
21
|
-
super.merge(
|
22
|
-
backtrace: []
|
23
|
-
)
|
21
|
+
super.merge(backtrace: [])
|
24
22
|
end
|
25
23
|
|
26
24
|
protected
|
data/lib/bullet/rack.rb
CHANGED
@@ -15,13 +15,19 @@ module Bullet
|
|
15
15
|
status, headers, response = @app.call(env)
|
16
16
|
|
17
17
|
response_body = nil
|
18
|
+
|
18
19
|
if Bullet.notification?
|
19
|
-
if !file?(headers) && !sse?(headers) && !empty?(response) &&
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
if Bullet.inject_into_page? && !file?(headers) && !sse?(headers) && !empty?(response) && status == 200
|
21
|
+
if html_request?(headers, response)
|
22
|
+
response_body = response_body(response)
|
23
|
+
response_body = append_to_html_body(response_body, footer_note) if Bullet.add_footer
|
24
|
+
response_body = append_to_html_body(response_body, Bullet.gather_inline_notifications)
|
25
|
+
response_body = append_to_html_body(response_body, xhr_script)
|
26
|
+
headers['Content-Length'] = response_body.bytesize.to_s
|
27
|
+
else
|
28
|
+
set_header(headers, 'X-bullet-footer-text', Bullet.footer_info.uniq) if Bullet.add_footer
|
29
|
+
set_header(headers, 'X-bullet-console-text', Bullet.text_notifications) if Bullet.console_enabled?
|
30
|
+
end
|
25
31
|
end
|
26
32
|
Bullet.perform_out_of_channel_notifications(env)
|
27
33
|
end
|
@@ -32,20 +38,15 @@ module Bullet
|
|
32
38
|
|
33
39
|
# fix issue if response's body is a Proc
|
34
40
|
def empty?(response)
|
35
|
-
# response may be ["Not Found"], ["Move Permanently"], etc
|
36
|
-
if
|
37
|
-
|
38
|
-
|
39
|
-
!response_body(response).respond_to?(:empty?) ||
|
40
|
-
response_body(response).empty?
|
41
|
-
else
|
42
|
-
body = response_body(response)
|
43
|
-
body.nil? || body.empty?
|
44
|
-
end
|
41
|
+
# response may be ["Not Found"], ["Move Permanently"], etc, but
|
42
|
+
# those should not happen if the status is 200
|
43
|
+
body = response_body(response)
|
44
|
+
body.nil? || body.empty?
|
45
45
|
end
|
46
46
|
|
47
47
|
def append_to_html_body(response_body, content)
|
48
48
|
body = response_body.dup
|
49
|
+
content = content.html_safe if content.respond_to?(:html_safe)
|
49
50
|
if body.include?('</body>')
|
50
51
|
position = body.rindex('</body>')
|
51
52
|
body.insert(position, content)
|
@@ -55,7 +56,15 @@ module Bullet
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def footer_note
|
58
|
-
"<
|
59
|
+
"<details #{details_attributes}><summary #{summary_attributes}>Bullet Warnings</summary><div #{footer_content_attributes}>#{Bullet.footer_info.uniq.join('<br>')}#{footer_console_message}</div></details>"
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_header(headers, header_name, header_array)
|
63
|
+
# Many proxy applications such as Nginx and AWS ELB limit
|
64
|
+
# the size a header to 8KB, so truncate the list of reports to
|
65
|
+
# be under that limit
|
66
|
+
header_array.pop while header_array.to_json.length > 8 * 1024
|
67
|
+
headers[header_name] = header_array.to_json
|
59
68
|
end
|
60
69
|
|
61
70
|
def file?(headers)
|
@@ -80,18 +89,34 @@ module Bullet
|
|
80
89
|
|
81
90
|
private
|
82
91
|
|
83
|
-
def
|
92
|
+
def details_attributes
|
93
|
+
<<~EOF
|
94
|
+
id="bullet-footer" data-is-bullet-footer
|
95
|
+
style="cursor: pointer; position: fixed; left: 0px; bottom: 0px; z-index: 9999; background: #fdf2f2; color: #9b1c1c; font-size: 12px; border-radius: 0px 8px 0px 0px; border: 1px solid #9b1c1c;"
|
96
|
+
EOF
|
97
|
+
end
|
98
|
+
|
99
|
+
def summary_attributes
|
100
|
+
<<~EOF
|
101
|
+
style="font-weight: 600; padding: 2px 8px"
|
102
|
+
EOF
|
103
|
+
end
|
104
|
+
|
105
|
+
def footer_content_attributes
|
84
106
|
<<~EOF
|
85
|
-
|
86
|
-
-moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none;
|
87
|
-
-moz-border-left-colors: none; -moz-border-image: none; border-width: 2pt 2pt 0px 0px;
|
88
|
-
padding: 3px 5px; border-radius: 0pt 10pt 0pt 0px; background: none repeat scroll 0% 0% rgba(200, 200, 200, 0.8);
|
89
|
-
color: rgb(119, 119, 119); font-size: 16px; font-family: 'Arial', sans-serif; z-index:9999;"
|
107
|
+
style="padding: 8px; border-top: 1px solid #9b1c1c;"
|
90
108
|
EOF
|
91
109
|
end
|
92
110
|
|
93
|
-
def
|
94
|
-
|
111
|
+
def footer_console_message
|
112
|
+
if Bullet.console_enabled?
|
113
|
+
"<br/><span style='font-style: italic;'>See 'Uniform Notifier' in JS Console for Stacktrace</span>"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Make footer work for XHR requests by appending data to the footer
|
118
|
+
def xhr_script
|
119
|
+
"<script type='text/javascript'>#{File.read("#{__dir__}/bullet_xhr.js")}</script>"
|
95
120
|
end
|
96
121
|
end
|
97
122
|
end
|