bullet 7.2.0 → 8.0.8
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/CHANGELOG.md +48 -1
- data/MIT-LICENSE +1 -1
- data/README.md +34 -7
- data/lib/bullet/active_record4.rb +4 -1
- data/lib/bullet/active_record41.rb +4 -1
- data/lib/bullet/active_record42.rb +4 -1
- data/lib/bullet/active_record5.rb +1 -0
- data/lib/bullet/active_record52.rb +1 -0
- data/lib/bullet/active_record60.rb +1 -0
- data/lib/bullet/active_record61.rb +1 -0
- data/lib/bullet/active_record70.rb +1 -0
- data/lib/bullet/active_record71.rb +1 -0
- data/lib/bullet/active_record72.rb +1 -0
- data/lib/bullet/active_record80.rb +319 -0
- data/lib/bullet/dependency.rb +16 -0
- data/lib/bullet/detector/association.rb +10 -8
- data/lib/bullet/detector/counter_cache.rb +4 -2
- data/lib/bullet/detector/n_plus_one_query.rb +21 -8
- data/lib/bullet/detector/unused_eager_loading.rb +3 -0
- data/lib/bullet/ext/object.rb +27 -20
- data/lib/bullet/ext/string.rb +10 -3
- data/lib/bullet/mongoid9x.rb +72 -0
- data/lib/bullet/rack.rb +55 -28
- data/lib/bullet/registry/base.rb +5 -1
- data/lib/bullet/registry/call_stack.rb +1 -1
- data/lib/bullet/registry/object.rb +3 -0
- data/lib/bullet/stack_trace_filter.rb +4 -4
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +36 -30
- metadata +6 -7
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
using Bullet::Ext::Object
|
4
|
+
|
3
5
|
module Bullet
|
4
6
|
module Detector
|
5
7
|
class Association < Base
|
@@ -34,7 +36,7 @@ module Bullet
|
|
34
36
|
# that the objects may cause N+1 query.
|
35
37
|
# e.g. { Post => ["Post:1", "Post:2"] }
|
36
38
|
def possible_objects
|
37
|
-
Thread.current
|
39
|
+
Thread.current.thread_variable_get(:bullet_possible_objects)
|
38
40
|
end
|
39
41
|
|
40
42
|
# impossible_objects keep the class to objects relationships
|
@@ -43,7 +45,7 @@ module Bullet
|
|
43
45
|
# if find collection returns only one object, then the object is impossible object,
|
44
46
|
# impossible_objects are used to avoid treating 1+1 query to N+1 query.
|
45
47
|
def impossible_objects
|
46
|
-
Thread.current
|
48
|
+
Thread.current.thread_variable_get(:bullet_impossible_objects)
|
47
49
|
end
|
48
50
|
|
49
51
|
private
|
@@ -54,7 +56,7 @@ module Bullet
|
|
54
56
|
# the object_associations keep all associations that may be or may no be
|
55
57
|
# unpreload associations or unused preload associations.
|
56
58
|
def object_associations
|
57
|
-
Thread.current
|
59
|
+
Thread.current.thread_variable_get(:bullet_object_associations)
|
58
60
|
end
|
59
61
|
|
60
62
|
# call_object_associations keep the object relationships
|
@@ -62,27 +64,27 @@ module Bullet
|
|
62
64
|
# e.g. { "Post:1" => [:comments] }
|
63
65
|
# they are used to detect unused preload associations.
|
64
66
|
def call_object_associations
|
65
|
-
Thread.current
|
67
|
+
Thread.current.thread_variable_get(:bullet_call_object_associations)
|
66
68
|
end
|
67
69
|
|
68
70
|
# inversed_objects keeps object relationships
|
69
71
|
# that association is inversed.
|
70
72
|
# e.g. { "Comment:1" => ["post"] }
|
71
73
|
def inversed_objects
|
72
|
-
Thread.current
|
74
|
+
Thread.current.thread_variable_get(:bullet_inversed_objects)
|
73
75
|
end
|
74
76
|
|
75
77
|
# eager_loadings keep the object relationships
|
76
78
|
# that the associations are preloaded by find :include.
|
77
79
|
# e.g. { ["Post:1", "Post:2"] => [:comments, :user] }
|
78
80
|
def eager_loadings
|
79
|
-
Thread.current
|
81
|
+
Thread.current.thread_variable_get(:bullet_eager_loadings)
|
80
82
|
end
|
81
83
|
|
82
|
-
#
|
84
|
+
# call_stacks keeps stacktraces where querie-objects were called from.
|
83
85
|
# e.g. { 'Object:111' => [SomeProject/app/controllers/...] }
|
84
86
|
def call_stacks
|
85
|
-
Thread.current
|
87
|
+
Thread.current.thread_variable_get(:bullet_call_stacks)
|
86
88
|
end
|
87
89
|
end
|
88
90
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
using Bullet::Ext::Object
|
4
|
+
|
3
5
|
module Bullet
|
4
6
|
module Detector
|
5
7
|
class CounterCache < Base
|
@@ -44,11 +46,11 @@ module Bullet
|
|
44
46
|
end
|
45
47
|
|
46
48
|
def possible_objects
|
47
|
-
Thread.current
|
49
|
+
Thread.current.thread_variable_get(:bullet_counter_possible_objects)
|
48
50
|
end
|
49
51
|
|
50
52
|
def impossible_objects
|
51
|
-
Thread.current
|
53
|
+
Thread.current.thread_variable_get(:bullet_counter_impossible_objects)
|
52
54
|
end
|
53
55
|
|
54
56
|
private
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
using Bullet::Ext::Object
|
4
|
+
|
3
5
|
module Bullet
|
4
6
|
module Detector
|
5
7
|
class NPlusOneQuery < Association
|
@@ -25,7 +27,7 @@ module Bullet
|
|
25
27
|
)
|
26
28
|
if !excluded_stacktrace_path? && conditions_met?(object, associations)
|
27
29
|
Bullet.debug('detect n + 1 query', "object: #{object.bullet_key}, associations: #{associations}")
|
28
|
-
create_notification
|
30
|
+
create_notification(caller_in_project(object.bullet_key), object.class.to_s, associations)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
@@ -36,16 +38,17 @@ module Bullet
|
|
36
38
|
objects = Array.wrap(object_or_objects)
|
37
39
|
class_names_match_regex = true
|
38
40
|
primary_key_values_are_empty = true
|
39
|
-
|
40
|
-
objects.
|
41
|
+
|
42
|
+
keys_joined = objects.map do |obj|
|
41
43
|
unless obj.class.name =~ /^HABTM_/
|
42
44
|
class_names_match_regex = false
|
43
45
|
end
|
44
46
|
unless obj.bullet_primary_key_value.nil?
|
45
47
|
primary_key_values_are_empty = false
|
46
48
|
end
|
47
|
-
|
48
|
-
end
|
49
|
+
obj.bullet_key
|
50
|
+
end.join(", ")
|
51
|
+
|
49
52
|
unless class_names_match_regex || primary_key_values_are_empty
|
50
53
|
Bullet.debug('Detector::NPlusOneQuery#add_possible_objects', "objects: #{keys_joined}")
|
51
54
|
objects.each { |object| possible_objects.add object.bullet_key }
|
@@ -64,13 +67,23 @@ module Bullet
|
|
64
67
|
def add_inversed_object(object, association)
|
65
68
|
return unless Bullet.start?
|
66
69
|
return unless Bullet.n_plus_one_query_enable?
|
67
|
-
return unless object.bullet_primary_key_value
|
68
70
|
|
71
|
+
object_key = object.bullet_primary_key_value ? object.bullet_key : object.object_id
|
69
72
|
Bullet.debug(
|
70
73
|
'Detector::NPlusOneQuery#add_inversed_object',
|
71
|
-
"object: #{
|
74
|
+
"object: #{object_key}, association: #{association}"
|
72
75
|
)
|
73
|
-
inversed_objects.add
|
76
|
+
inversed_objects.add object_key, association
|
77
|
+
end
|
78
|
+
|
79
|
+
def update_inversed_object(object)
|
80
|
+
if inversed_objects&.key?(object.object_id)
|
81
|
+
Bullet.debug(
|
82
|
+
'Detector::NPlusOneQuery#update_inversed_object',
|
83
|
+
"object from #{object.object_id} to #{object.bullet_key}"
|
84
|
+
)
|
85
|
+
inversed_objects.add(object.bullet_key, inversed_objects[object.object_id].to_a)
|
86
|
+
end
|
74
87
|
end
|
75
88
|
|
76
89
|
# decide whether the object.associations is unpreloaded or not.
|
data/lib/bullet/ext/object.rb
CHANGED
@@ -1,30 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Bullet
|
4
|
+
module Ext
|
5
|
+
module Object
|
6
|
+
refine ::Object do
|
7
|
+
attr_writer :bullet_key, :bullet_primary_key_value
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
def bullet_key
|
10
|
+
return "#{self.class}:" if respond_to?(:persisted?) && !persisted?
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
elsif self.class.respond_to?(:primary_key) && self.class.primary_key
|
14
|
-
primary_key = self.class.primary_key
|
15
|
-
else
|
16
|
-
primary_key = :id
|
17
|
-
end
|
12
|
+
@bullet_key ||= "#{self.class}:#{bullet_primary_key_value}"
|
13
|
+
end
|
18
14
|
|
19
|
-
|
20
|
-
|
15
|
+
def bullet_primary_key_value
|
16
|
+
return if respond_to?(:persisted?) && !persisted?
|
21
17
|
|
22
|
-
|
18
|
+
@bullet_primary_key_value ||=
|
19
|
+
begin
|
20
|
+
primary_key = self.class.try(:primary_keys) || self.class.try(:primary_key) || :id
|
23
21
|
|
24
|
-
|
25
|
-
|
22
|
+
bullet_join_potential_composite_primary_key(primary_key)
|
23
|
+
end
|
24
|
+
end
|
26
25
|
|
27
|
-
|
28
|
-
|
26
|
+
private
|
27
|
+
|
28
|
+
def bullet_join_potential_composite_primary_key(primary_keys)
|
29
|
+
return read_attribute(primary_keys) unless primary_keys.is_a?(Enumerable)
|
30
|
+
|
31
|
+
primary_keys.map { |primary_key| read_attribute primary_key }
|
32
|
+
.compact.join(',')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
29
36
|
end
|
30
37
|
end
|
data/lib/bullet/ext/string.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Bullet
|
4
|
+
module Ext
|
5
|
+
module String
|
6
|
+
refine ::String do
|
7
|
+
def bullet_class_name
|
8
|
+
last_colon = self.rindex(':')
|
9
|
+
last_colon ? self[0...last_colon].dup : self.dup
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
6
13
|
end
|
7
14
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bullet
|
4
|
+
module Mongoid
|
5
|
+
def self.enable
|
6
|
+
require 'mongoid'
|
7
|
+
require 'rubygems'
|
8
|
+
::Mongoid::Contextual::Mongo.class_eval do
|
9
|
+
alias_method :origin_first, :first
|
10
|
+
alias_method :origin_last, :last
|
11
|
+
alias_method :origin_each, :each
|
12
|
+
alias_method :origin_eager_load, :eager_load
|
13
|
+
|
14
|
+
%i[first last].each do |context|
|
15
|
+
default = Gem::Version.new(::Mongoid::VERSION) >= Gem::Version.new('7.5') ? nil : {}
|
16
|
+
define_method(context) do |opts = default|
|
17
|
+
result = send(:"origin_#{context}", opts)
|
18
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def each(&_block)
|
24
|
+
return to_enum unless block_given?
|
25
|
+
|
26
|
+
first_document = nil
|
27
|
+
document_count = 0
|
28
|
+
|
29
|
+
origin_each do |document|
|
30
|
+
document_count += 1
|
31
|
+
|
32
|
+
if document_count == 1
|
33
|
+
first_document = document
|
34
|
+
elsif document_count == 2
|
35
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects([first_document, document])
|
36
|
+
yield(first_document)
|
37
|
+
first_document = nil
|
38
|
+
yield(document)
|
39
|
+
else
|
40
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(document)
|
41
|
+
yield(document)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if document_count == 1
|
46
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(first_document)
|
47
|
+
yield(first_document)
|
48
|
+
end
|
49
|
+
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def eager_load(docs)
|
54
|
+
associations = criteria.inclusions.map(&:name)
|
55
|
+
docs.each { |doc| Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations) }
|
56
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
|
57
|
+
origin_eager_load(docs)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
::Mongoid::Association::Accessors.class_eval do
|
62
|
+
alias_method :origin_get_relation, :get_relation
|
63
|
+
|
64
|
+
def get_relation(name, association, object, reload = false)
|
65
|
+
result = origin_get_relation(name, association, object, reload)
|
66
|
+
Bullet::Detector::NPlusOneQuery.call_association(self, name) unless association.embedded?
|
67
|
+
result
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/bullet/rack.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'rack/request'
|
4
|
+
require 'json'
|
5
|
+
require 'cgi'
|
6
|
+
|
3
7
|
module Bullet
|
4
8
|
class Rack
|
5
9
|
include Dependency
|
6
10
|
|
7
|
-
NONCE_MATCHER = /script-src .*'nonce-(?<nonce>[A-Za-z0-9+\/]+={0,2})'/
|
11
|
+
NONCE_MATCHER = /(script|style)-src .*'nonce-(?<nonce>[A-Za-z0-9+\/]+={0,2})'/
|
8
12
|
|
9
13
|
def initialize(app)
|
10
14
|
@app = app
|
@@ -19,12 +23,13 @@ module Bullet
|
|
19
23
|
response_body = nil
|
20
24
|
|
21
25
|
if Bullet.notification? || Bullet.always_append_html_body
|
22
|
-
|
26
|
+
request = ::Rack::Request.new(env)
|
27
|
+
if Bullet.inject_into_page? && !skip_html_injection?(request) && !file?(headers) && !sse?(headers) && !empty?(response) && status == 200
|
23
28
|
if html_request?(headers, response)
|
24
29
|
response_body = response_body(response)
|
25
30
|
|
26
31
|
with_security_policy_nonce(headers) do |nonce|
|
27
|
-
response_body = append_to_html_body(response_body, footer_note) if Bullet.add_footer
|
32
|
+
response_body = append_to_html_body(response_body, footer_note(nonce)) if Bullet.add_footer
|
28
33
|
response_body = append_to_html_body(response_body, Bullet.gather_inline_notifications)
|
29
34
|
if Bullet.add_footer && !Bullet.skip_http_headers
|
30
35
|
response_body = append_to_html_body(response_body, xhr_script(nonce))
|
@@ -65,16 +70,48 @@ module Bullet
|
|
65
70
|
end
|
66
71
|
end
|
67
72
|
|
68
|
-
def footer_note
|
69
|
-
|
73
|
+
def footer_note(nonce = nil)
|
74
|
+
%(<details id="bullet-footer" data-is-bullet-footer><summary>Bullet Warnings</summary><div>#{Bullet.footer_info.uniq.join('<br>')}#{footer_console_message(nonce)}</div>#{footer_style(nonce)}</details>)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Make footer styles work with ContentSecurityPolicy style-src as self
|
78
|
+
def footer_style(nonce = nil)
|
79
|
+
css = <<~CSS
|
80
|
+
details#bullet-footer {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;}
|
81
|
+
details#bullet-footer summary {font-weight: 600; padding: 2px 8px;}
|
82
|
+
details#bullet-footer div {padding: 8px; border-top: 1px solid #9b1c1c;}
|
83
|
+
CSS
|
84
|
+
if nonce
|
85
|
+
%(<style type="text/css" nonce="#{nonce}">#{css}</style>)
|
86
|
+
else
|
87
|
+
%(<style type="text/css">#{css}</style>)
|
88
|
+
end
|
70
89
|
end
|
71
90
|
|
72
91
|
def set_header(headers, header_name, header_array)
|
73
92
|
# Many proxy applications such as Nginx and AWS ELB limit
|
74
93
|
# the size a header to 8KB, so truncate the list of reports to
|
75
94
|
# be under that limit
|
76
|
-
header_array.pop while header_array.
|
77
|
-
headers[header_name] = header_array
|
95
|
+
header_array.pop while JSON.generate(header_array).length > 8 * 1024
|
96
|
+
headers[header_name] = JSON.generate(header_array)
|
97
|
+
end
|
98
|
+
|
99
|
+
def skip_html_injection?(request)
|
100
|
+
query_string = request.env['QUERY_STRING']
|
101
|
+
return false if query_string.nil? || query_string.empty?
|
102
|
+
|
103
|
+
params = simple_parse_query_string(query_string)
|
104
|
+
params['skip_html_injection'] == 'true'
|
105
|
+
end
|
106
|
+
|
107
|
+
# Simple query string parser
|
108
|
+
def simple_parse_query_string(query_string)
|
109
|
+
params = {}
|
110
|
+
query_string.split('&').each do |pair|
|
111
|
+
key, value = pair.split('=', 2).map { |s| CGI.unescape(s) }
|
112
|
+
params[key] = value if key && !key.empty?
|
113
|
+
end
|
114
|
+
params
|
78
115
|
end
|
79
116
|
|
80
117
|
def file?(headers)
|
@@ -99,28 +136,18 @@ module Bullet
|
|
99
136
|
|
100
137
|
private
|
101
138
|
|
102
|
-
def
|
103
|
-
<<~EOF
|
104
|
-
id="bullet-footer" data-is-bullet-footer
|
105
|
-
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;"
|
106
|
-
EOF
|
107
|
-
end
|
108
|
-
|
109
|
-
def summary_attributes
|
110
|
-
<<~EOF
|
111
|
-
style="font-weight: 600; padding: 2px 8px"
|
112
|
-
EOF
|
113
|
-
end
|
114
|
-
|
115
|
-
def footer_content_attributes
|
116
|
-
<<~EOF
|
117
|
-
style="padding: 8px; border-top: 1px solid #9b1c1c;"
|
118
|
-
EOF
|
119
|
-
end
|
120
|
-
|
121
|
-
def footer_console_message
|
139
|
+
def footer_console_message(nonce = nil)
|
122
140
|
if Bullet.console_enabled?
|
123
|
-
|
141
|
+
footer = %(<br/><span id="console-message">See 'Uniform Notifier' in JS Console for Stacktrace</span>)
|
142
|
+
css = "details#bullet-footer #console-message {font-style: italic;}"
|
143
|
+
style =
|
144
|
+
if nonce
|
145
|
+
%(<style type="text/css" nonce="#{nonce}">#{css}</style>)
|
146
|
+
else
|
147
|
+
%(<style type="text/css">#{css}</style>)
|
148
|
+
end
|
149
|
+
|
150
|
+
footer + style
|
124
151
|
end
|
125
152
|
end
|
126
153
|
|
data/lib/bullet/registry/base.rb
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
require "bundler"
|
4
4
|
|
5
|
+
using Bullet::Ext::Object
|
6
|
+
|
5
7
|
module Bullet
|
6
8
|
module StackTraceFilter
|
7
9
|
VENDOR_PATH = '/vendor'
|
8
|
-
IS_RUBY_19 = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
|
9
10
|
|
10
11
|
# @param bullet_key[String] - use this to get stored call stack from call_stacks object.
|
11
12
|
def caller_in_project(bullet_key = nil)
|
@@ -54,13 +55,12 @@ module Bullet
|
|
54
55
|
def location_as_path(location)
|
55
56
|
return location if location.is_a?(String)
|
56
57
|
|
57
|
-
|
58
|
+
location.absolute_path.to_s
|
58
59
|
end
|
59
60
|
|
60
61
|
def select_caller_locations(bullet_key = nil)
|
61
|
-
return caller.select { |caller_path| yield caller_path } if IS_RUBY_19
|
62
|
-
|
63
62
|
call_stack = bullet_key ? call_stacks[bullet_key] : caller_locations
|
63
|
+
|
64
64
|
call_stack.select { |location| yield location }
|
65
65
|
end
|
66
66
|
end
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
3
4
|
require 'active_support/core_ext/module/delegation'
|
4
5
|
require 'set'
|
5
6
|
require 'uniform_notifier'
|
@@ -22,8 +23,8 @@ module Bullet
|
|
22
23
|
|
23
24
|
if defined?(Rails::Railtie)
|
24
25
|
class BulletRailtie < Rails::Railtie
|
25
|
-
initializer 'bullet.
|
26
|
-
if defined?(ActionDispatch::ContentSecurityPolicy::Middleware) && Rails.application.config.content_security_policy
|
26
|
+
initializer 'bullet.add_middleware', after: :load_config_initializers do |app|
|
27
|
+
if defined?(ActionDispatch::ContentSecurityPolicy::Middleware) && Rails.application.config.content_security_policy && !app.config.api_only
|
27
28
|
app.middleware.insert_before ActionDispatch::ContentSecurityPolicy::Middleware, Bullet::Rack
|
28
29
|
else
|
29
30
|
app.middleware.use Bullet::Rack
|
@@ -63,7 +64,7 @@ module Bullet
|
|
63
64
|
].freeze
|
64
65
|
|
65
66
|
def enable=(enable)
|
66
|
-
@enable =
|
67
|
+
@enable = enable
|
67
68
|
|
68
69
|
if enable?
|
69
70
|
reset_safelist
|
@@ -89,15 +90,15 @@ module Bullet
|
|
89
90
|
end
|
90
91
|
|
91
92
|
def n_plus_one_query_enable?
|
92
|
-
enable? &&
|
93
|
+
enable? && (@n_plus_one_query_enable.nil? ? true : @n_plus_one_query_enable)
|
93
94
|
end
|
94
95
|
|
95
96
|
def unused_eager_loading_enable?
|
96
|
-
enable? &&
|
97
|
+
enable? && (@unused_eager_loading_enable.nil? ? true : @unused_eager_loading_enable)
|
97
98
|
end
|
98
99
|
|
99
100
|
def counter_cache_enable?
|
100
|
-
enable? &&
|
101
|
+
enable? && (@counter_cache_enable.nil? ? true : @counter_cache_enable)
|
101
102
|
end
|
102
103
|
|
103
104
|
def stacktrace_includes
|
@@ -148,42 +149,47 @@ module Bullet
|
|
148
149
|
end
|
149
150
|
|
150
151
|
def start_request
|
151
|
-
Thread.current
|
152
|
-
Thread.current
|
153
|
-
|
154
|
-
Thread.current
|
155
|
-
Thread.current
|
156
|
-
Thread.current
|
157
|
-
Thread.current
|
158
|
-
Thread.current
|
159
|
-
Thread.current
|
160
|
-
Thread.current
|
152
|
+
Thread.current.thread_variable_set(:bullet_start, true)
|
153
|
+
Thread.current.thread_variable_set(:bullet_notification_collector, Bullet::NotificationCollector.new)
|
154
|
+
|
155
|
+
Thread.current.thread_variable_set(:bullet_object_associations, Bullet::Registry::Base.new)
|
156
|
+
Thread.current.thread_variable_set(:bullet_call_object_associations, Bullet::Registry::Base.new)
|
157
|
+
Thread.current.thread_variable_set(:bullet_possible_objects, Bullet::Registry::Object.new)
|
158
|
+
Thread.current.thread_variable_set(:bullet_impossible_objects, Bullet::Registry::Object.new)
|
159
|
+
Thread.current.thread_variable_set(:bullet_inversed_objects, Bullet::Registry::Base.new)
|
160
|
+
Thread.current.thread_variable_set(:bullet_eager_loadings, Bullet::Registry::Association.new)
|
161
|
+
Thread.current.thread_variable_set(:bullet_call_stacks, Bullet::Registry::CallStack.new)
|
162
|
+
|
163
|
+
unless Thread.current.thread_variable_get(:bullet_counter_possible_objects)
|
164
|
+
Thread.current.thread_variable_set(:bullet_counter_possible_objects, Bullet::Registry::Object.new)
|
165
|
+
end
|
161
166
|
|
162
|
-
Thread.current
|
163
|
-
|
167
|
+
unless Thread.current.thread_variable_get(:bullet_counter_impossible_objects)
|
168
|
+
Thread.current.thread_variable_set(:bullet_counter_impossible_objects, Bullet::Registry::Object.new)
|
169
|
+
end
|
164
170
|
end
|
165
171
|
|
166
172
|
def end_request
|
167
|
-
Thread.current
|
168
|
-
Thread.current
|
173
|
+
Thread.current.thread_variable_set(:bullet_start, nil)
|
174
|
+
Thread.current.thread_variable_set(:bullet_notification_collector, nil)
|
169
175
|
|
170
|
-
Thread.current
|
171
|
-
Thread.current
|
172
|
-
Thread.current
|
173
|
-
Thread.current
|
174
|
-
Thread.current
|
175
|
-
Thread.current
|
176
|
+
Thread.current.thread_variable_set(:bullet_object_associations, nil)
|
177
|
+
Thread.current.thread_variable_set(:bullet_call_object_associations, nil)
|
178
|
+
Thread.current.thread_variable_set(:bullet_possible_objects, nil)
|
179
|
+
Thread.current.thread_variable_set(:bullet_impossible_objects, nil)
|
180
|
+
Thread.current.thread_variable_set(:bullet_inversed_objects, nil)
|
181
|
+
Thread.current.thread_variable_set(:bullet_eager_loadings, nil)
|
176
182
|
|
177
|
-
Thread.current
|
178
|
-
Thread.current
|
183
|
+
Thread.current.thread_variable_set(:bullet_counter_possible_objects, nil)
|
184
|
+
Thread.current.thread_variable_set(:bullet_counter_impossible_objects, nil)
|
179
185
|
end
|
180
186
|
|
181
187
|
def start?
|
182
|
-
enable? && Thread.current
|
188
|
+
enable? && Thread.current.thread_variable_get(:bullet_start)
|
183
189
|
end
|
184
190
|
|
185
191
|
def notification_collector
|
186
|
-
Thread.current
|
192
|
+
Thread.current.thread_variable_get(:bullet_notification_collector)
|
187
193
|
end
|
188
194
|
|
189
195
|
def notification?
|