bullet 6.1.0 → 7.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +82 -0
- data/CHANGELOG.md +45 -0
- data/Gemfile.rails-6.0 +1 -1
- data/Gemfile.rails-6.1 +15 -0
- data/Gemfile.rails-7.0 +10 -0
- data/README.md +37 -25
- data/lib/bullet/active_job.rb +5 -1
- data/lib/bullet/active_record41.rb +1 -0
- data/lib/bullet/active_record42.rb +1 -0
- data/lib/bullet/active_record5.rb +1 -1
- data/lib/bullet/active_record52.rb +23 -18
- data/lib/bullet/active_record60.rb +23 -18
- data/lib/bullet/active_record61.rb +272 -0
- data/lib/bullet/active_record70.rb +275 -0
- data/lib/bullet/bullet_xhr.js +18 -17
- data/lib/bullet/dependency.rb +16 -0
- data/lib/bullet/detector/base.rb +2 -1
- data/lib/bullet/detector/counter_cache.rb +2 -2
- data/lib/bullet/detector/n_plus_one_query.rb +5 -5
- data/lib/bullet/detector/unused_eager_loading.rb +2 -2
- data/lib/bullet/mongoid4x.rb +1 -1
- data/lib/bullet/mongoid5x.rb +1 -1
- data/lib/bullet/mongoid6x.rb +1 -1
- data/lib/bullet/mongoid7x.rb +24 -7
- data/lib/bullet/notification.rb +2 -1
- data/lib/bullet/rack.rb +28 -19
- data/lib/bullet/stack_trace_filter.rb +7 -9
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +29 -28
- data/lib/generators/bullet/install_generator.rb +22 -25
- data/perf/benchmark.rb +4 -1
- data/spec/bullet/detector/counter_cache_spec.rb +1 -1
- data/spec/bullet/detector/n_plus_one_query_spec.rb +1 -1
- data/spec/bullet/detector/unused_eager_loading_spec.rb +10 -10
- data/spec/bullet/ext/object_spec.rb +1 -1
- data/spec/bullet/notification/base_spec.rb +4 -4
- data/spec/bullet/notification/n_plus_one_query_spec.rb +1 -3
- data/spec/bullet/rack_spec.rb +135 -9
- data/spec/bullet_spec.rb +15 -15
- data/spec/integration/active_record/association_spec.rb +64 -10
- data/spec/integration/counter_cache_spec.rb +4 -4
- data/spec/integration/mongoid/association_spec.rb +4 -4
- data/spec/models/attachment.rb +5 -0
- data/spec/models/deal.rb +5 -0
- data/spec/models/folder.rb +2 -1
- data/spec/models/group.rb +2 -1
- data/spec/models/page.rb +2 -1
- data/spec/models/post.rb +2 -0
- data/spec/models/role.rb +7 -0
- data/spec/models/submission.rb +1 -0
- data/spec/models/user.rb +2 -0
- data/spec/models/writer.rb +2 -1
- data/spec/spec_helper.rb +0 -2
- data/spec/support/mongo_seed.rb +1 -0
- data/spec/support/sqlite_seed.rb +38 -0
- data/test.sh +2 -0
- metadata +17 -7
- data/.travis.yml +0 -33
@@ -7,7 +7,7 @@ module Bullet
|
|
7
7
|
extend StackTraceFilter
|
8
8
|
|
9
9
|
class << self
|
10
|
-
# executed when object.
|
10
|
+
# executed when object.associations is called.
|
11
11
|
# first, it keeps this method call for object.association.
|
12
12
|
# then, it checks if this associations call is unpreload.
|
13
13
|
# if it is, keeps this unpreload associations and caller.
|
@@ -33,8 +33,9 @@ module Bullet
|
|
33
33
|
return unless Bullet.start?
|
34
34
|
return unless Bullet.n_plus_one_query_enable?
|
35
35
|
|
36
|
-
objects = Array(object_or_objects)
|
36
|
+
objects = Array.wrap(object_or_objects)
|
37
37
|
return if objects.map(&:bullet_primary_key_value).compact.empty?
|
38
|
+
return if objects.all? { |obj| obj.class.name =~ /^HABTM_/ }
|
38
39
|
|
39
40
|
Bullet.debug(
|
40
41
|
'Detector::NPlusOneQuery#add_possible_objects',
|
@@ -84,8 +85,7 @@ module Bullet
|
|
84
85
|
# associations == v comparison order is important here because
|
85
86
|
# v variable might be a squeel node where :== method is redefined,
|
86
87
|
# so it does not compare values at all and return unexpected results
|
87
|
-
result =
|
88
|
-
v.is_a?(Hash) ? v.key?(associations) : associations == v
|
88
|
+
result = v.is_a?(Hash) ? v.key?(associations) : associations == v
|
89
89
|
return true if result
|
90
90
|
end
|
91
91
|
|
@@ -95,7 +95,7 @@ module Bullet
|
|
95
95
|
private
|
96
96
|
|
97
97
|
def create_notification(callers, klazz, associations)
|
98
|
-
notify_associations = Array(associations) - Bullet.
|
98
|
+
notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:n_plus_one_query, klazz)
|
99
99
|
|
100
100
|
if notify_associations.present?
|
101
101
|
notice = Bullet::Notification::NPlusOneQuery.new(callers, klazz, notify_associations)
|
@@ -10,7 +10,7 @@ module Bullet
|
|
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
|
13
|
-
# if association not in call_object_association, then the object => association - call_object_association is ununsed preload
|
13
|
+
# if association not in call_object_association, then the object => association - call_object_association is ununsed preload associations
|
14
14
|
def check_unused_preload_associations
|
15
15
|
return unless Bullet.start?
|
16
16
|
return unless Bullet.unused_eager_loading_enable?
|
@@ -65,7 +65,7 @@ module Bullet
|
|
65
65
|
private
|
66
66
|
|
67
67
|
def create_notification(callers, klazz, associations)
|
68
|
-
notify_associations = Array(associations) - Bullet.
|
68
|
+
notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:unused_eager_loading, klazz)
|
69
69
|
|
70
70
|
if notify_associations.present?
|
71
71
|
notice = Bullet::Notification::UnusedEagerLoading.new(callers, klazz, notify_associations)
|
data/lib/bullet/mongoid4x.rb
CHANGED
data/lib/bullet/mongoid5x.rb
CHANGED
data/lib/bullet/mongoid6x.rb
CHANGED
data/lib/bullet/mongoid7x.rb
CHANGED
@@ -25,14 +25,31 @@ module Bullet
|
|
25
25
|
def each(&block)
|
26
26
|
return to_enum unless block_given?
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
first_document = nil
|
29
|
+
document_count = 0
|
30
|
+
|
31
|
+
origin_each do |document|
|
32
|
+
document_count += 1
|
33
|
+
|
34
|
+
if document_count == 1
|
35
|
+
first_document = document
|
36
|
+
elsif document_count == 2
|
37
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects([first_document, document])
|
38
|
+
yield(first_document)
|
39
|
+
first_document = nil
|
40
|
+
yield(document)
|
41
|
+
else
|
42
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(document)
|
43
|
+
yield(document)
|
44
|
+
end
|
34
45
|
end
|
35
|
-
|
46
|
+
|
47
|
+
if document_count == 1
|
48
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(first_document)
|
49
|
+
yield(first_document)
|
50
|
+
end
|
51
|
+
|
52
|
+
self
|
36
53
|
end
|
37
54
|
|
38
55
|
def eager_load(docs)
|
data/lib/bullet/notification.rb
CHANGED
data/lib/bullet/rack.rb
CHANGED
@@ -17,14 +17,16 @@ module Bullet
|
|
17
17
|
response_body = nil
|
18
18
|
|
19
19
|
if Bullet.notification?
|
20
|
-
if
|
20
|
+
if Bullet.inject_into_page? && !file?(headers) && !sse?(headers) && !empty?(response) && status == 200
|
21
21
|
if html_request?(headers, response)
|
22
22
|
response_body = response_body(response)
|
23
23
|
response_body = append_to_html_body(response_body, footer_note) if Bullet.add_footer
|
24
24
|
response_body = append_to_html_body(response_body, Bullet.gather_inline_notifications)
|
25
|
-
|
25
|
+
if Bullet.add_footer && !Bullet.skip_http_headers
|
26
|
+
response_body = append_to_html_body(response_body, xhr_script)
|
27
|
+
end
|
26
28
|
headers['Content-Length'] = response_body.bytesize.to_s
|
27
|
-
|
29
|
+
elsif !Bullet.skip_http_headers
|
28
30
|
set_header(headers, 'X-bullet-footer-text', Bullet.footer_info.uniq) if Bullet.add_footer
|
29
31
|
set_header(headers, 'X-bullet-console-text', Bullet.text_notifications) if Bullet.console_enabled?
|
30
32
|
end
|
@@ -40,12 +42,14 @@ module Bullet
|
|
40
42
|
def empty?(response)
|
41
43
|
# response may be ["Not Found"], ["Move Permanently"], etc, but
|
42
44
|
# those should not happen if the status is 200
|
45
|
+
return true if !response.respond_to?(:body) && !response.respond_to?(:first)
|
43
46
|
body = response_body(response)
|
44
47
|
body.nil? || body.empty?
|
45
48
|
end
|
46
49
|
|
47
50
|
def append_to_html_body(response_body, content)
|
48
51
|
body = response_body.dup
|
52
|
+
content = content.html_safe if content.respond_to?(:html_safe)
|
49
53
|
if body.include?('</body>')
|
50
54
|
position = body.rindex('</body>')
|
51
55
|
body.insert(position, content)
|
@@ -55,14 +59,14 @@ module Bullet
|
|
55
59
|
end
|
56
60
|
|
57
61
|
def footer_note
|
58
|
-
"<
|
62
|
+
"<details #{details_attributes}><summary #{summary_attributes}>Bullet Warnings</summary><div #{footer_content_attributes}>#{Bullet.footer_info.uniq.join('<br>')}#{footer_console_message}</div></details>"
|
59
63
|
end
|
60
64
|
|
61
65
|
def set_header(headers, header_name, header_array)
|
62
66
|
# Many proxy applications such as Nginx and AWS ELB limit
|
63
67
|
# the size a header to 8KB, so truncate the list of reports to
|
64
68
|
# be under that limit
|
65
|
-
header_array.pop while header_array.to_json.length > 8 *
|
69
|
+
header_array.pop while header_array.to_json.length > 8 * 1024
|
66
70
|
headers[header_name] = header_array.to_json
|
67
71
|
end
|
68
72
|
|
@@ -75,36 +79,41 @@ module Bullet
|
|
75
79
|
end
|
76
80
|
|
77
81
|
def html_request?(headers, response)
|
78
|
-
headers['Content-Type']&.include?('text/html')
|
82
|
+
headers['Content-Type']&.include?('text/html')
|
79
83
|
end
|
80
84
|
|
81
85
|
def response_body(response)
|
82
86
|
if response.respond_to?(:body)
|
83
87
|
Array === response.body ? response.body.first : response.body
|
84
|
-
|
88
|
+
elsif response.respond_to?(:first)
|
85
89
|
response.first
|
86
90
|
end
|
87
91
|
end
|
88
92
|
|
89
93
|
private
|
90
94
|
|
91
|
-
def
|
95
|
+
def details_attributes
|
96
|
+
<<~EOF
|
97
|
+
id="bullet-footer" data-is-bullet-footer
|
98
|
+
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;"
|
99
|
+
EOF
|
100
|
+
end
|
101
|
+
|
102
|
+
def summary_attributes
|
92
103
|
<<~EOF
|
93
|
-
|
94
|
-
-moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none;
|
95
|
-
-moz-border-left-colors: none; -moz-border-image: none; border-width: 2pt 2pt 0px 0px;
|
96
|
-
padding: 3px 5px; border-radius: 0pt 10pt 0pt 0px; background: none repeat scroll 0% 0% rgba(200, 200, 200, 0.8);
|
97
|
-
color: rgb(119, 119, 119); font-size: 16px; font-family: 'Arial', sans-serif; z-index:9999;"
|
104
|
+
style="font-weight: 600; padding: 2px 8px"
|
98
105
|
EOF
|
99
106
|
end
|
100
107
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
108
|
+
def footer_content_attributes
|
109
|
+
<<~EOF
|
110
|
+
style="padding: 8px; border-top: 1px solid #9b1c1c;"
|
111
|
+
EOF
|
112
|
+
end
|
113
|
+
|
114
|
+
def footer_console_message
|
104
115
|
if Bullet.console_enabled?
|
105
|
-
"<span>See 'Uniform Notifier' in JS Console for Stacktrace</span
|
106
|
-
else
|
107
|
-
cancel_button
|
116
|
+
"<br/><span style='font-style: italic;'>See 'Uniform Notifier' in JS Console for Stacktrace</span>"
|
108
117
|
end
|
109
118
|
end
|
110
119
|
|
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "bundler"
|
2
3
|
|
3
4
|
module Bullet
|
4
5
|
module StackTraceFilter
|
5
6
|
VENDOR_PATH = '/vendor'
|
7
|
+
IS_RUBY_19 = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0')
|
6
8
|
|
7
9
|
def caller_in_project
|
8
10
|
vendor_root = Bullet.app_root + VENDOR_PATH
|
@@ -10,8 +12,9 @@ module Bullet
|
|
10
12
|
select_caller_locations do |location|
|
11
13
|
caller_path = location_as_path(location)
|
12
14
|
caller_path.include?(Bullet.app_root) && !caller_path.include?(vendor_root) &&
|
13
|
-
!caller_path.include?(bundler_path) ||
|
14
|
-
|
15
|
+
!caller_path.include?(bundler_path) || Bullet.stacktrace_includes.any? { |include_pattern|
|
16
|
+
pattern_matches?(location, include_pattern)
|
17
|
+
}
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
@@ -47,20 +50,15 @@ module Bullet
|
|
47
50
|
end
|
48
51
|
|
49
52
|
def location_as_path(location)
|
50
|
-
|
53
|
+
IS_RUBY_19 ? location : location.absolute_path.to_s
|
51
54
|
end
|
52
55
|
|
53
56
|
def select_caller_locations
|
54
|
-
if
|
57
|
+
if IS_RUBY_19
|
55
58
|
caller.select { |caller_path| yield caller_path }
|
56
59
|
else
|
57
60
|
caller_locations.select { |location| yield location }
|
58
61
|
end
|
59
62
|
end
|
60
|
-
|
61
|
-
def ruby_19?
|
62
|
-
@ruby_19 = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0.0') if @ruby_19.nil?
|
63
|
-
@ruby_19
|
64
|
-
end
|
65
63
|
end
|
66
64
|
end
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
@@ -20,9 +20,6 @@ module Bullet
|
|
20
20
|
autoload :Registry, 'bullet/registry'
|
21
21
|
autoload :NotificationCollector, 'bullet/notification_collector'
|
22
22
|
|
23
|
-
BULLET_DEBUG = 'BULLET_DEBUG'
|
24
|
-
TRUE = 'true'
|
25
|
-
|
26
23
|
if defined?(Rails::Railtie)
|
27
24
|
class BulletRailtie < Rails::Railtie
|
28
25
|
initializer 'bullet.configure_rails_initialization' do |app|
|
@@ -38,10 +35,11 @@ module Bullet
|
|
38
35
|
:stacktrace_includes,
|
39
36
|
:stacktrace_excludes,
|
40
37
|
:skip_html_injection
|
41
|
-
attr_reader :
|
42
|
-
attr_accessor :add_footer, :orm_patches_applied
|
38
|
+
attr_reader :safelist
|
39
|
+
attr_accessor :add_footer, :orm_patches_applied, :skip_http_headers
|
43
40
|
|
44
|
-
available_notifiers =
|
41
|
+
available_notifiers =
|
42
|
+
UniformNotifier::AVAILABLE_NOTIFIERS.select { |notifier| notifier != :raise }.map { |notifier| "#{notifier}=" }
|
45
43
|
available_notifiers_options = { to: UniformNotifier }
|
46
44
|
delegate(*available_notifiers, **available_notifiers_options)
|
47
45
|
|
@@ -59,7 +57,7 @@ module Bullet
|
|
59
57
|
@enable = @n_plus_one_query_enable = @unused_eager_loading_enable = @counter_cache_enable = enable
|
60
58
|
|
61
59
|
if enable?
|
62
|
-
|
60
|
+
reset_safelist
|
63
61
|
unless orm_patches_applied
|
64
62
|
self.orm_patches_applied = true
|
65
63
|
Bullet::Mongoid.enable if mongoid?
|
@@ -72,8 +70,9 @@ module Bullet
|
|
72
70
|
!!@enable
|
73
71
|
end
|
74
72
|
|
73
|
+
# Rails.root might be nil if `railties` is a dependency on a project that does not use Rails
|
75
74
|
def app_root
|
76
|
-
(defined?(::Rails.root) ? Rails.root.to_s : Dir.pwd).to_s
|
75
|
+
@app_root ||= (defined?(::Rails.root) && !::Rails.root.nil? ? Rails.root.to_s : Dir.pwd).to_s
|
77
76
|
end
|
78
77
|
|
79
78
|
def n_plus_one_query_enable?
|
@@ -89,36 +88,36 @@ module Bullet
|
|
89
88
|
end
|
90
89
|
|
91
90
|
def stacktrace_includes
|
92
|
-
@stacktrace_includes
|
91
|
+
@stacktrace_includes ||= []
|
93
92
|
end
|
94
93
|
|
95
94
|
def stacktrace_excludes
|
96
|
-
@stacktrace_excludes
|
95
|
+
@stacktrace_excludes ||= []
|
97
96
|
end
|
98
97
|
|
99
|
-
def
|
100
|
-
|
101
|
-
@
|
102
|
-
@
|
98
|
+
def add_safelist(options)
|
99
|
+
reset_safelist
|
100
|
+
@safelist[options[:type]][options[:class_name]] ||= []
|
101
|
+
@safelist[options[:type]][options[:class_name]] << options[:association].to_sym
|
103
102
|
end
|
104
103
|
|
105
|
-
def
|
106
|
-
|
107
|
-
@
|
108
|
-
@
|
109
|
-
@
|
104
|
+
def delete_safelist(options)
|
105
|
+
reset_safelist
|
106
|
+
@safelist[options[:type]][options[:class_name]] ||= []
|
107
|
+
@safelist[options[:type]][options[:class_name]].delete(options[:association].to_sym)
|
108
|
+
@safelist[options[:type]].delete_if { |_key, val| val.empty? }
|
110
109
|
end
|
111
110
|
|
112
|
-
def
|
113
|
-
Array(@
|
111
|
+
def get_safelist_associations(type, class_name)
|
112
|
+
Array.wrap(@safelist[type][class_name])
|
114
113
|
end
|
115
114
|
|
116
|
-
def
|
117
|
-
@
|
115
|
+
def reset_safelist
|
116
|
+
@safelist ||= { n_plus_one_query: {}, unused_eager_loading: {}, counter_cache: {} }
|
118
117
|
end
|
119
118
|
|
120
|
-
def
|
121
|
-
@
|
119
|
+
def clear_safelist
|
120
|
+
@safelist = nil
|
122
121
|
end
|
123
122
|
|
124
123
|
def bullet_logger=(active)
|
@@ -132,7 +131,7 @@ module Bullet
|
|
132
131
|
end
|
133
132
|
|
134
133
|
def debug(title, message)
|
135
|
-
puts "[Bullet][#{title}] #{message}" if ENV[BULLET_DEBUG] ==
|
134
|
+
puts "[Bullet][#{title}] #{message}" if ENV['BULLET_DEBUG'] == 'true'
|
136
135
|
end
|
137
136
|
|
138
137
|
def start_request
|
@@ -240,8 +239,10 @@ module Bullet
|
|
240
239
|
UniformNotifier.active_notifiers.include?(UniformNotifier::JavascriptConsole)
|
241
240
|
end
|
242
241
|
|
243
|
-
def
|
244
|
-
@skip_html_injection
|
242
|
+
def inject_into_page?
|
243
|
+
return false if defined?(@skip_html_injection) && @skip_html_injection
|
244
|
+
|
245
|
+
console_enabled? || add_footer
|
245
246
|
end
|
246
247
|
|
247
248
|
private
|
@@ -10,40 +10,37 @@ module Bullet
|
|
10
10
|
|
11
11
|
def enable_in_development
|
12
12
|
environment(nil, env: 'development') do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
13
|
+
<<~FILE
|
14
|
+
config.after_initialize do
|
15
|
+
Bullet.enable = true
|
16
|
+
Bullet.alert = true
|
17
|
+
Bullet.bullet_logger = true
|
18
|
+
Bullet.console = true
|
19
|
+
Bullet.rails_logger = true
|
20
|
+
Bullet.add_footer = true
|
21
|
+
end
|
22
|
+
|
24
23
|
FILE
|
25
|
-
.strip
|
26
24
|
end
|
27
25
|
|
28
26
|
say 'Enabled bullet in config/environments/development.rb'
|
29
27
|
end
|
30
28
|
|
31
29
|
def enable_in_test
|
32
|
-
|
33
|
-
environment(nil, env: 'test') do
|
34
|
-
<<-"FILE"
|
35
|
-
|
36
|
-
config.after_initialize do
|
37
|
-
Bullet.enable = true
|
38
|
-
Bullet.bullet_logger = true
|
39
|
-
Bullet.raise = true # raise an error if n+1 query occurs
|
40
|
-
end
|
41
|
-
FILE
|
42
|
-
.strip
|
43
|
-
end
|
30
|
+
return unless yes?('Would you like to enable bullet in test environment? (y/n)')
|
44
31
|
|
45
|
-
|
32
|
+
environment(nil, env: 'test') do
|
33
|
+
<<~FILE
|
34
|
+
config.after_initialize do
|
35
|
+
Bullet.enable = true
|
36
|
+
Bullet.bullet_logger = true
|
37
|
+
Bullet.raise = true # raise an error if n+1 query occurs
|
38
|
+
end
|
39
|
+
|
40
|
+
FILE
|
46
41
|
end
|
42
|
+
|
43
|
+
say 'Enabled bullet in config/environments/test.rb'
|
47
44
|
end
|
48
45
|
end
|
49
46
|
end
|
data/perf/benchmark.rb
CHANGED
@@ -30,7 +30,10 @@ end
|
|
30
30
|
|
31
31
|
# create database bullet_benchmark;
|
32
32
|
ActiveRecord::Base.establish_connection(
|
33
|
-
adapter: 'mysql2',
|
33
|
+
adapter: 'mysql2',
|
34
|
+
database: 'bullet_benchmark',
|
35
|
+
server: '/tmp/mysql.socket',
|
36
|
+
username: 'root'
|
34
37
|
)
|
35
38
|
|
36
39
|
ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
@@ -47,7 +47,7 @@ module Bullet
|
|
47
47
|
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
48
48
|
end
|
49
49
|
|
50
|
-
it 'should be
|
50
|
+
it 'should be false when object is possible, and impossible' do
|
51
51
|
CounterCache.add_possible_objects(@post1)
|
52
52
|
CounterCache.add_impossible_object(@post1)
|
53
53
|
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
@@ -39,7 +39,7 @@ module Bullet
|
|
39
39
|
|
40
40
|
it 'should be false if object, association pair is not existed' do
|
41
41
|
NPlusOneQuery.add_object_associations(@post, :association1)
|
42
|
-
expect(NPlusOneQuery.association?(@post, :
|
42
|
+
expect(NPlusOneQuery.association?(@post, :association2)).to eq false
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -13,27 +13,27 @@ module Bullet
|
|
13
13
|
|
14
14
|
context '.call_associations' do
|
15
15
|
it 'should get empty array if eager_loadings' do
|
16
|
-
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new(
|
16
|
+
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'should get call associations if object and association are both in eager_loadings and call_object_associations' do
|
20
20
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
21
21
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
22
|
-
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new(
|
23
|
-
|
22
|
+
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to eq(
|
23
|
+
[:association]
|
24
24
|
)
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'should not get call associations if not exist in call_object_associations' do
|
28
28
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
29
|
-
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new(
|
29
|
+
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
context '.diff_object_associations' do
|
34
34
|
it 'should return associations not exist in call_association' do
|
35
|
-
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new(
|
36
|
-
|
35
|
+
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to eq(
|
36
|
+
[:association]
|
37
37
|
)
|
38
38
|
end
|
39
39
|
|
@@ -41,7 +41,7 @@ module Bullet
|
|
41
41
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
42
42
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
43
43
|
expect(
|
44
|
-
UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new(
|
44
|
+
UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))
|
45
45
|
).to be_empty
|
46
46
|
end
|
47
47
|
end
|
@@ -51,7 +51,7 @@ module Bullet
|
|
51
51
|
it 'should create notification if object_association_diff is not empty' do
|
52
52
|
UnusedEagerLoading.add_object_associations(@post, :association)
|
53
53
|
allow(UnusedEagerLoading).to receive(:caller_in_project).and_return(paths)
|
54
|
-
expect(UnusedEagerLoading).to receive(:create_notification).with(paths, 'Post',
|
54
|
+
expect(UnusedEagerLoading).to receive(:create_notification).with(paths, 'Post', [:association])
|
55
55
|
UnusedEagerLoading.check_unused_preload_associations
|
56
56
|
end
|
57
57
|
|
@@ -60,9 +60,9 @@ module Bullet
|
|
60
60
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
61
61
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
62
62
|
expect(
|
63
|
-
UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new(
|
63
|
+
UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))
|
64
64
|
).to be_empty
|
65
|
-
expect(UnusedEagerLoading).not_to receive(:create_notification).with('Post',
|
65
|
+
expect(UnusedEagerLoading).not_to receive(:create_notification).with('Post', [:association])
|
66
66
|
UnusedEagerLoading.check_unused_preload_associations
|
67
67
|
end
|
68
68
|
end
|
@@ -10,7 +10,7 @@ describe Object do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
if mongoid?
|
13
|
-
it 'should return class with
|
13
|
+
it 'should return class with namespace and id composition' do
|
14
14
|
post = Mongoid::Post.first
|
15
15
|
expect(post.bullet_key).to eq("Mongoid::Post:#{post.id}")
|
16
16
|
end
|
@@ -74,8 +74,8 @@ module Bullet
|
|
74
74
|
it 'should send full_notice to notifier' do
|
75
75
|
notifier = double
|
76
76
|
allow(subject).to receive(:notifier).and_return(notifier)
|
77
|
-
allow(subject).to receive(:notification_data).and_return(foo: :bar)
|
78
|
-
expect(notifier).to receive(:inline_notify).with(foo: :bar)
|
77
|
+
allow(subject).to receive(:notification_data).and_return({ foo: :bar })
|
78
|
+
expect(notifier).to receive(:inline_notify).with({ foo: :bar })
|
79
79
|
subject.notify_inline
|
80
80
|
end
|
81
81
|
end
|
@@ -84,8 +84,8 @@ module Bullet
|
|
84
84
|
it 'should send full_out_of_channel to notifier' do
|
85
85
|
notifier = double
|
86
86
|
allow(subject).to receive(:notifier).and_return(notifier)
|
87
|
-
allow(subject).to receive(:notification_data).and_return(foo: :bar)
|
88
|
-
expect(notifier).to receive(:out_of_channel_notify).with(foo: :bar)
|
87
|
+
allow(subject).to receive(:notification_data).and_return({ foo: :bar })
|
88
|
+
expect(notifier).to receive(:out_of_channel_notify).with({ foo: :bar })
|
89
89
|
subject.notify_out_of_channel
|
90
90
|
end
|
91
91
|
end
|
@@ -21,9 +21,7 @@ module Bullet
|
|
21
21
|
)
|
22
22
|
end
|
23
23
|
it do
|
24
|
-
expect(subject.body).to eq(
|
25
|
-
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])"
|
26
|
-
)
|
24
|
+
expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])")
|
27
25
|
end
|
28
26
|
it { expect(subject.title).to eq('USE eager loading in path') }
|
29
27
|
end
|