bullet 5.6.0 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.rails-5.2 +15 -0
- data/Guardfile +2 -2
- data/Rakefile +16 -17
- data/bullet.gemspec +11 -11
- data/lib/bullet/active_record52.rb +225 -0
- data/lib/bullet/dependency.rb +6 -0
- data/lib/bullet/detector/association.rb +3 -2
- data/lib/bullet/detector/counter_cache.rb +4 -3
- data/lib/bullet/detector/n_plus_one_query.rb +6 -5
- data/lib/bullet/detector/unused_eager_loading.rb +4 -3
- data/lib/bullet/ext/string.rb +1 -1
- data/lib/bullet/mongoid4x.rb +1 -1
- data/lib/bullet/mongoid5x.rb +1 -1
- data/lib/bullet/mongoid6x.rb +1 -1
- data/lib/bullet/notification/base.rb +9 -8
- data/lib/bullet/notification/counter_cache.rb +1 -1
- data/lib/bullet/notification/n_plus_one_query.rb +2 -1
- data/lib/bullet/notification/unused_eager_loading.rb +2 -1
- data/lib/bullet/rack.rb +5 -5
- data/lib/bullet/stack_trace_filter.rb +2 -2
- data/lib/bullet/version.rb +2 -2
- data/lib/bullet.rb +15 -7
- data/lib/generators/bullet/install_generator.rb +5 -5
- data/perf/benchmark.rb +6 -8
- data/spec/bullet/detector/association_spec.rb +4 -4
- data/spec/bullet/detector/counter_cache_spec.rb +11 -11
- data/spec/bullet/detector/n_plus_one_query_spec.rb +35 -35
- data/spec/bullet/detector/unused_eager_loading_spec.rb +19 -19
- data/spec/bullet/ext/object_spec.rb +7 -7
- data/spec/bullet/ext/string_spec.rb +5 -5
- data/spec/bullet/notification/base_spec.rb +32 -33
- data/spec/bullet/notification/counter_cache_spec.rb +2 -2
- data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +2 -2
- data/spec/bullet/notification_collector_spec.rb +10 -10
- data/spec/bullet/rack_spec.rb +46 -46
- data/spec/bullet/registry/association_spec.rb +10 -10
- data/spec/bullet/registry/base_spec.rb +20 -20
- data/spec/bullet/registry/object_spec.rb +4 -4
- data/spec/bullet_spec.rb +20 -1
- data/spec/integration/active_record/association_spec.rb +106 -106
- data/spec/integration/counter_cache_spec.rb +12 -12
- data/spec/integration/mongoid/association_spec.rb +33 -33
- data/spec/models/comment.rb +1 -1
- data/spec/models/document.rb +2 -2
- data/spec/models/mongoid/address.rb +1 -1
- data/spec/models/mongoid/category.rb +2 -2
- data/spec/models/mongoid/comment.rb +1 -1
- data/spec/models/mongoid/company.rb +1 -1
- data/spec/models/mongoid/entry.rb +1 -1
- data/spec/models/mongoid/post.rb +3 -3
- data/spec/models/newspaper.rb +1 -1
- data/spec/spec_helper.rb +12 -12
- data/spec/support/mongo_seed.rb +6 -6
- data/spec/support/rack_double.rb +4 -3
- data/spec/support/sqlite_seed.rb +6 -7
- data/tasks/bullet_tasks.rake +2 -2
- data/test.sh +2 -0
- data/update.sh +2 -0
- metadata +5 -3
data/lib/bullet/rack.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Bullet
|
|
|
14
14
|
response_body = nil
|
|
15
15
|
if Bullet.notification?
|
|
16
16
|
if !file?(headers) && !sse?(headers) && !empty?(response) &&
|
|
17
|
-
|
|
17
|
+
status == 200 && !response_body(response).frozen? && html_request?(headers, response)
|
|
18
18
|
response_body = response_body(response)
|
|
19
19
|
append_to_html_body(response_body, footer_note) if Bullet.add_footer
|
|
20
20
|
append_to_html_body(response_body, Bullet.gather_inline_notifications)
|
|
@@ -51,19 +51,19 @@ module Bullet
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def footer_note
|
|
54
|
-
"<div #{footer_div_attributes}>" + footer_close_button + Bullet.footer_info.uniq.join(
|
|
54
|
+
"<div #{footer_div_attributes}>" + footer_close_button + Bullet.footer_info.uniq.join('<br>') + '</div>'
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def file?(headers)
|
|
58
|
-
headers[
|
|
58
|
+
headers['Content-Transfer-Encoding'] == 'binary' || headers['Content-Disposition']
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def sse?(headers)
|
|
62
|
-
headers[
|
|
62
|
+
headers['Content-Type'] == 'text/event-stream'
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def html_request?(headers, response)
|
|
66
|
-
headers['Content-Type'] && headers['Content-Type'].include?('text/html') && response_body(response).include?(
|
|
66
|
+
headers['Content-Type'] && headers['Content-Type'].include?('text/html') && response_body(response).include?('<html')
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def response_body(response)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module Bullet
|
|
2
2
|
module StackTraceFilter
|
|
3
|
-
VENDOR_PATH =
|
|
3
|
+
VENDOR_PATH = '/vendor'.freeze
|
|
4
4
|
|
|
5
5
|
def caller_in_project
|
|
6
6
|
app_root = rails? ? Rails.root.to_s : Dir.pwd
|
|
7
7
|
vendor_root = app_root + VENDOR_PATH
|
|
8
8
|
caller_locations.select do |location|
|
|
9
|
-
caller_path = location.absolute_path
|
|
9
|
+
caller_path = location.absolute_path.to_s
|
|
10
10
|
caller_path.include?(app_root) && !caller_path.include?(vendor_root) ||
|
|
11
11
|
Bullet.stacktrace_includes.any? do |include_pattern|
|
|
12
12
|
case include_pattern
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
|
2
2
|
require 'set'
|
|
3
3
|
require 'uniform_notifier'
|
|
4
4
|
require 'bullet/ext/object'
|
|
@@ -22,7 +22,7 @@ module Bullet
|
|
|
22
22
|
|
|
23
23
|
if defined? Rails::Railtie
|
|
24
24
|
class BulletRailtie < Rails::Railtie
|
|
25
|
-
initializer
|
|
25
|
+
initializer 'bullet.configure_rails_initialization' do |app|
|
|
26
26
|
app.middleware.use Bullet::Rack
|
|
27
27
|
end
|
|
28
28
|
end
|
|
@@ -38,12 +38,12 @@ module Bullet
|
|
|
38
38
|
delegate *available_notifiers
|
|
39
39
|
|
|
40
40
|
def raise=(should_raise)
|
|
41
|
-
UniformNotifier.raise=(should_raise ? Notification::UnoptimizedQueryError : false)
|
|
41
|
+
UniformNotifier.raise = (should_raise ? Notification::UnoptimizedQueryError : false)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
DETECTORS = [
|
|
44
|
+
DETECTORS = [Bullet::Detector::NPlusOneQuery,
|
|
45
45
|
Bullet::Detector::UnusedEagerLoading,
|
|
46
|
-
Bullet::Detector::CounterCache
|
|
46
|
+
Bullet::Detector::CounterCache].freeze
|
|
47
47
|
|
|
48
48
|
def enable=(enable)
|
|
49
49
|
@enable = @n_plus_one_query_enable = @unused_eager_loading_enable = @counter_cache_enable = enable
|
|
@@ -87,12 +87,19 @@ module Bullet
|
|
|
87
87
|
@whitelist[options[:type]][options[:class_name]] << options[:association].to_sym
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
+
def delete_whitelist(options)
|
|
91
|
+
reset_whitelist
|
|
92
|
+
@whitelist[options[:type]][options[:class_name]] ||= []
|
|
93
|
+
@whitelist[options[:type]][options[:class_name]].delete(options[:association].to_sym)
|
|
94
|
+
@whitelist[options[:type]].delete_if { |key, val| val.empty? }
|
|
95
|
+
end
|
|
96
|
+
|
|
90
97
|
def get_whitelist_associations(type, class_name)
|
|
91
98
|
Array(@whitelist[type][class_name])
|
|
92
99
|
end
|
|
93
100
|
|
|
94
101
|
def reset_whitelist
|
|
95
|
-
@whitelist ||= {:n_plus_one_query => {}, :unused_eager_loading => {}, :counter_cache => {}}
|
|
102
|
+
@whitelist ||= { :n_plus_one_query => {}, :unused_eager_loading => {}, :counter_cache => {} }
|
|
96
103
|
end
|
|
97
104
|
|
|
98
105
|
def clear_whitelist
|
|
@@ -163,7 +170,7 @@ module Bullet
|
|
|
163
170
|
for_each_active_notifier_with_notification do |notification|
|
|
164
171
|
responses << notification.notify_inline
|
|
165
172
|
end
|
|
166
|
-
responses.join(
|
|
173
|
+
responses.join("\n")
|
|
167
174
|
end
|
|
168
175
|
|
|
169
176
|
def perform_out_of_channel_notifications(env = {})
|
|
@@ -211,6 +218,7 @@ module Bullet
|
|
|
211
218
|
end
|
|
212
219
|
|
|
213
220
|
private
|
|
221
|
+
|
|
214
222
|
def for_each_active_notifier_with_notification
|
|
215
223
|
UniformNotifier.active_notifiers.each do |notifier|
|
|
216
224
|
notification_collector.collection.each do |notification|
|
|
@@ -7,7 +7,7 @@ Description:
|
|
|
7
7
|
DESC
|
|
8
8
|
|
|
9
9
|
def enable_in_development
|
|
10
|
-
environment(nil, env:
|
|
10
|
+
environment(nil, env: 'development') do
|
|
11
11
|
<<-"FILE".strip
|
|
12
12
|
|
|
13
13
|
config.after_initialize do
|
|
@@ -22,12 +22,12 @@ Description:
|
|
|
22
22
|
FILE
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
say
|
|
25
|
+
say 'Enabled bullet in config/environments/development.rb'
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def enable_in_test
|
|
29
|
-
if yes?(
|
|
30
|
-
environment(nil, env:
|
|
29
|
+
if yes?('Would you like to enable bullet in test environment? (y/n)')
|
|
30
|
+
environment(nil, env: 'test') do
|
|
31
31
|
<<-"FILE".strip
|
|
32
32
|
|
|
33
33
|
config.after_initialize do
|
|
@@ -38,7 +38,7 @@ Description:
|
|
|
38
38
|
FILE
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
say
|
|
41
|
+
say 'Enabled bullet in config/environments/test.rb'
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
end
|
data/perf/benchmark.rb
CHANGED
|
@@ -53,7 +53,7 @@ end
|
|
|
53
53
|
|
|
54
54
|
users_size = 100
|
|
55
55
|
posts_size = 1000
|
|
56
|
-
comments_size =
|
|
56
|
+
comments_size = 10_000
|
|
57
57
|
users = []
|
|
58
58
|
users_size.times do |i|
|
|
59
59
|
users << User.new(:name => "user#{i}")
|
|
@@ -63,19 +63,18 @@ users = User.all
|
|
|
63
63
|
|
|
64
64
|
posts = []
|
|
65
65
|
posts_size.times do |i|
|
|
66
|
-
posts << Post.new(:title => "Title #{i}", :body => "Body #{i}", :user => users[i%100])
|
|
66
|
+
posts << Post.new(:title => "Title #{i}", :body => "Body #{i}", :user => users[i % 100])
|
|
67
67
|
end
|
|
68
68
|
Post.import posts
|
|
69
69
|
posts = Post.all
|
|
70
70
|
|
|
71
71
|
comments = []
|
|
72
72
|
comments_size.times do |i|
|
|
73
|
-
comments << Comment.new(:body => "Comment #{i}", :post => posts[i%1000], :user => users[i%100])
|
|
73
|
+
comments << Comment.new(:body => "Comment #{i}", :post => posts[i % 1000], :user => users[i % 100])
|
|
74
74
|
end
|
|
75
75
|
Comment.import comments
|
|
76
76
|
|
|
77
|
-
puts
|
|
78
|
-
|
|
77
|
+
puts 'Start benchmarking...'
|
|
79
78
|
|
|
80
79
|
Bullet.enable = true
|
|
81
80
|
|
|
@@ -83,7 +82,7 @@ Benchmark.bm(70) do |bm|
|
|
|
83
82
|
bm.report("Querying & Iterating #{posts_size} Posts with #{comments_size} Comments and #{users_size} Users") do
|
|
84
83
|
10.times do
|
|
85
84
|
Bullet.start_request
|
|
86
|
-
Post.select(
|
|
85
|
+
Post.select('SQL_NO_CACHE *').includes(:user, :comments => :user).each do |p|
|
|
87
86
|
p.title
|
|
88
87
|
p.user.name
|
|
89
88
|
p.comments.each do |c|
|
|
@@ -96,8 +95,7 @@ Benchmark.bm(70) do |bm|
|
|
|
96
95
|
end
|
|
97
96
|
end
|
|
98
97
|
|
|
99
|
-
puts
|
|
100
|
-
|
|
98
|
+
puts 'End benchmarking...'
|
|
101
99
|
|
|
102
100
|
# Run benchmark with bundler
|
|
103
101
|
#
|
|
@@ -8,15 +8,15 @@ module Bullet
|
|
|
8
8
|
@post2 = Post.last
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
context
|
|
12
|
-
it
|
|
11
|
+
context '.add_object_association' do
|
|
12
|
+
it 'should add object, associations pair' do
|
|
13
13
|
Association.add_object_associations(@post1, :associations)
|
|
14
14
|
expect(Association.send(:object_associations)).to be_include(@post1.bullet_key, :associations)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
context
|
|
19
|
-
it
|
|
18
|
+
context '.add_call_object_associations' do
|
|
19
|
+
it 'should add call object, associations pair' do
|
|
20
20
|
Association.add_call_object_associations(@post1, :associations)
|
|
21
21
|
expect(Association.send(:call_object_associations)).to be_include(@post1.bullet_key, :associations)
|
|
22
22
|
end
|
|
@@ -8,44 +8,44 @@ module Bullet
|
|
|
8
8
|
@post2 = Post.last
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
context
|
|
12
|
-
it
|
|
11
|
+
context '.add_counter_cache' do
|
|
12
|
+
it 'should create notification if conditions met' do
|
|
13
13
|
expect(CounterCache).to receive(:conditions_met?).with(@post1, [:comments]).and_return(true)
|
|
14
|
-
expect(CounterCache).to receive(:create_notification).with(
|
|
14
|
+
expect(CounterCache).to receive(:create_notification).with('Post', [:comments])
|
|
15
15
|
CounterCache.add_counter_cache(@post1, [:comments])
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
it
|
|
18
|
+
it 'should not create notification if conditions not met' do
|
|
19
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
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
context
|
|
26
|
-
it
|
|
25
|
+
context '.add_possible_objects' do
|
|
26
|
+
it 'should add possible objects' do
|
|
27
27
|
CounterCache.add_possible_objects([@post1, @post2])
|
|
28
28
|
expect(CounterCache.possible_objects).to be_include(@post1.bullet_key)
|
|
29
29
|
expect(CounterCache.possible_objects).to be_include(@post2.bullet_key)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
it
|
|
32
|
+
it 'should add impossible object' do
|
|
33
33
|
CounterCache.add_impossible_object(@post1)
|
|
34
34
|
expect(CounterCache.impossible_objects).to be_include(@post1.bullet_key)
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
context
|
|
39
|
-
it
|
|
38
|
+
context '.conditions_met?' do
|
|
39
|
+
it 'should be true when object is possible, not impossible' do
|
|
40
40
|
CounterCache.add_possible_objects(@post1)
|
|
41
41
|
expect(CounterCache.conditions_met?(@post1, :associations)).to eq true
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
it
|
|
44
|
+
it 'should be false when object is not possible' do
|
|
45
45
|
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
it
|
|
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
51
|
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
|
@@ -8,62 +8,62 @@ module Bullet
|
|
|
8
8
|
@post2 = Post.last
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
context
|
|
12
|
-
it
|
|
11
|
+
context '.call_association' do
|
|
12
|
+
it 'should add call_object_associations' do
|
|
13
13
|
expect(NPlusOneQuery).to receive(:add_call_object_associations).with(@post, :associations)
|
|
14
14
|
NPlusOneQuery.call_association(@post, :associations)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
context
|
|
19
|
-
it
|
|
18
|
+
context '.possible?' do
|
|
19
|
+
it 'should be true if possible_objects contain' do
|
|
20
20
|
NPlusOneQuery.add_possible_objects(@post)
|
|
21
21
|
expect(NPlusOneQuery.possible?(@post)).to eq true
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
context
|
|
26
|
-
it
|
|
25
|
+
context '.impossible?' do
|
|
26
|
+
it 'should be true if impossible_objects contain' do
|
|
27
27
|
NPlusOneQuery.add_impossible_object(@post)
|
|
28
28
|
expect(NPlusOneQuery.impossible?(@post)).to eq true
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
context
|
|
33
|
-
it
|
|
32
|
+
context '.association?' do
|
|
33
|
+
it 'should be true if object, associations pair is already existed' do
|
|
34
34
|
NPlusOneQuery.add_object_associations(@post, :association)
|
|
35
35
|
expect(NPlusOneQuery.association?(@post, :association)).to eq true
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
it
|
|
38
|
+
it 'should be false if object, association pair is not existed' do
|
|
39
39
|
NPlusOneQuery.add_object_associations(@post, :association1)
|
|
40
40
|
expect(NPlusOneQuery.association?(@post, :associatio2)).to eq false
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
context
|
|
45
|
-
it
|
|
44
|
+
context '.conditions_met?' do
|
|
45
|
+
it 'should be true if object is possible, not impossible and object, associations pair is not already existed' do
|
|
46
46
|
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
|
47
47
|
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
|
48
48
|
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
|
49
49
|
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq true
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
it
|
|
52
|
+
it 'should be false if object is not possible, not impossible and object, associations pair is not already existed' do
|
|
53
53
|
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(false)
|
|
54
54
|
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
|
55
55
|
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
|
56
56
|
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
it
|
|
59
|
+
it 'should be false if object is possible, but impossible and object, associations pair is not already existed' do
|
|
60
60
|
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
|
61
61
|
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(true)
|
|
62
62
|
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
|
63
63
|
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
it
|
|
66
|
+
it 'should be false if object is possible, not impossible and object, associations pair is already existed' do
|
|
67
67
|
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
|
68
68
|
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
|
69
69
|
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(true)
|
|
@@ -71,26 +71,26 @@ module Bullet
|
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
context
|
|
75
|
-
it
|
|
74
|
+
context '.call_association' do
|
|
75
|
+
it 'should create notification if conditions met' do
|
|
76
76
|
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
|
77
|
-
expect(NPlusOneQuery).to receive(:caller_in_project).and_return([
|
|
78
|
-
expect(NPlusOneQuery).to receive(:create_notification).with([
|
|
77
|
+
expect(NPlusOneQuery).to receive(:caller_in_project).and_return(['caller'])
|
|
78
|
+
expect(NPlusOneQuery).to receive(:create_notification).with(['caller'], 'Post', :association)
|
|
79
79
|
NPlusOneQuery.call_association(@post, :association)
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
-
it
|
|
82
|
+
it 'should not create notification if conditions not met' do
|
|
83
83
|
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(false)
|
|
84
84
|
expect(NPlusOneQuery).not_to receive(:caller_in_project!)
|
|
85
|
-
expect(NPlusOneQuery).not_to receive(:create_notification).with(
|
|
85
|
+
expect(NPlusOneQuery).not_to receive(:create_notification).with('Post', :association)
|
|
86
86
|
NPlusOneQuery.call_association(@post, :association)
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
context
|
|
90
|
-
before { Bullet.stacktrace_excludes = [
|
|
89
|
+
context 'stacktrace_excludes' do
|
|
90
|
+
before { Bullet.stacktrace_excludes = [/def/] }
|
|
91
91
|
after { Bullet.stacktrace_excludes = nil }
|
|
92
92
|
|
|
93
|
-
it
|
|
93
|
+
it 'should not create notification when stacktrace contains paths that are in the exclude list' do
|
|
94
94
|
in_project = OpenStruct.new(:absolute_path => File.join(Dir.pwd, 'abc', 'abc.rb'))
|
|
95
95
|
included_path = OpenStruct.new(:absolute_path => '/ghi/ghi.rb')
|
|
96
96
|
excluded_path = OpenStruct.new(:absolute_path => '/def/def.rb')
|
|
@@ -102,48 +102,48 @@ module Bullet
|
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
context
|
|
106
|
-
it
|
|
105
|
+
context '.caller_in_project' do
|
|
106
|
+
it 'should include only paths that are in the project' do
|
|
107
107
|
in_project = OpenStruct.new(:absolute_path => File.join(Dir.pwd, 'abc', 'abc.rb'))
|
|
108
108
|
not_in_project = OpenStruct.new(:absolute_path => '/def/def.rb')
|
|
109
109
|
|
|
110
110
|
expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, not_in_project])
|
|
111
111
|
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
|
112
|
-
expect(NPlusOneQuery).to receive(:create_notification).with([in_project],
|
|
112
|
+
expect(NPlusOneQuery).to receive(:create_notification).with([in_project], 'Post', :association)
|
|
113
113
|
NPlusOneQuery.call_association(@post, :association)
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
-
context
|
|
117
|
-
before { Bullet.stacktrace_includes = [
|
|
116
|
+
context 'stacktrace_includes' do
|
|
117
|
+
before { Bullet.stacktrace_includes = ['def', /xyz/] }
|
|
118
118
|
after { Bullet.stacktrace_includes = nil }
|
|
119
119
|
|
|
120
|
-
it
|
|
120
|
+
it 'should include paths that are in the stacktrace_include list' do
|
|
121
121
|
in_project = OpenStruct.new(:absolute_path => File.join(Dir.pwd, 'abc', 'abc.rb'))
|
|
122
122
|
included_gems = [OpenStruct.new(:absolute_path => '/def/def.rb'), OpenStruct.new(:absolute_path => 'xyz/xyz.rb')]
|
|
123
123
|
excluded_gem = OpenStruct.new(:absolute_path => '/ghi/ghi.rb')
|
|
124
124
|
|
|
125
125
|
expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, *included_gems, excluded_gem])
|
|
126
126
|
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
|
127
|
-
expect(NPlusOneQuery).to receive(:create_notification).with([in_project, *included_gems],
|
|
127
|
+
expect(NPlusOneQuery).to receive(:create_notification).with([in_project, *included_gems], 'Post', :association)
|
|
128
128
|
NPlusOneQuery.call_association(@post, :association)
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
-
context
|
|
134
|
-
it
|
|
133
|
+
context '.add_possible_objects' do
|
|
134
|
+
it 'should add possible objects' do
|
|
135
135
|
NPlusOneQuery.add_possible_objects([@post, @post2])
|
|
136
136
|
expect(NPlusOneQuery.possible_objects).to be_include(@post.bullet_key)
|
|
137
137
|
expect(NPlusOneQuery.possible_objects).to be_include(@post2.bullet_key)
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
-
it
|
|
140
|
+
it 'should not raise error if object is nil' do
|
|
141
141
|
expect { NPlusOneQuery.add_possible_objects(nil) }.not_to raise_error
|
|
142
142
|
end
|
|
143
143
|
end
|
|
144
144
|
|
|
145
|
-
context
|
|
146
|
-
it
|
|
145
|
+
context '.add_impossible_object' do
|
|
146
|
+
it 'should add impossible object' do
|
|
147
147
|
NPlusOneQuery.add_impossible_object(@post)
|
|
148
148
|
expect(NPlusOneQuery.impossible_objects).to be_include(@post.bullet_key)
|
|
149
149
|
end
|
|
@@ -9,68 +9,68 @@ module Bullet
|
|
|
9
9
|
@post3 = Post.last
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
context
|
|
13
|
-
it
|
|
12
|
+
context '.call_associations' do
|
|
13
|
+
it 'should get empty array if eager_loadings' do
|
|
14
14
|
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
it
|
|
17
|
+
it 'should get call associations if object and association are both in eager_loadings and call_object_associations' do
|
|
18
18
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
|
19
19
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
|
20
20
|
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to eq([:association])
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
it
|
|
23
|
+
it 'should not get call associations if not exist in call_object_associations' do
|
|
24
24
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
|
25
25
|
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
context
|
|
30
|
-
it
|
|
29
|
+
context '.diff_object_associations' do
|
|
30
|
+
it 'should return associations not exist in call_association' do
|
|
31
31
|
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to eq([:association])
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
it
|
|
34
|
+
it 'should return empty if associations exist in call_association' do
|
|
35
35
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
|
36
36
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
|
37
37
|
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
context
|
|
42
|
-
let(:paths) { [
|
|
43
|
-
it
|
|
41
|
+
context '.check_unused_preload_associations' do
|
|
42
|
+
let(:paths) { ['/dir1', '/dir1/subdir'] }
|
|
43
|
+
it 'should create notification if object_association_diff is not empty' do
|
|
44
44
|
UnusedEagerLoading.add_object_associations(@post, :association)
|
|
45
45
|
allow(UnusedEagerLoading).to receive(:caller_in_project).and_return(paths)
|
|
46
|
-
expect(UnusedEagerLoading).to receive(:create_notification).with(paths,
|
|
46
|
+
expect(UnusedEagerLoading).to receive(:create_notification).with(paths, 'Post', [:association])
|
|
47
47
|
UnusedEagerLoading.check_unused_preload_associations
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
it
|
|
50
|
+
it 'should not create notification if object_association_diff is empty' do
|
|
51
51
|
UnusedEagerLoading.add_object_associations(@post, :association)
|
|
52
52
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
|
53
53
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
|
54
54
|
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
|
55
|
-
expect(UnusedEagerLoading).not_to receive(:create_notification).with(
|
|
55
|
+
expect(UnusedEagerLoading).not_to receive(:create_notification).with('Post', [:association])
|
|
56
56
|
UnusedEagerLoading.check_unused_preload_associations
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
context
|
|
61
|
-
it
|
|
60
|
+
context '.add_eager_loadings' do
|
|
61
|
+
it 'should add objects, associations pair when eager_loadings are empty' do
|
|
62
62
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :associations)
|
|
63
63
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :associations)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
it
|
|
66
|
+
it 'should add objects, associations pair for existing eager_loadings' do
|
|
67
67
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
|
|
68
68
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
|
|
69
69
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :association1)
|
|
70
70
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :association2)
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
it
|
|
73
|
+
it 'should merge objects, associations pair for existing eager_loadings' do
|
|
74
74
|
UnusedEagerLoading.add_eager_loadings([@post], :association1)
|
|
75
75
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
|
|
76
76
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
|
|
@@ -78,7 +78,7 @@ module Bullet
|
|
|
78
78
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association2)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
it
|
|
81
|
+
it 'should vmerge objects recursively, associations pair for existing eager_loadings' do
|
|
82
82
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
|
|
83
83
|
UnusedEagerLoading.add_eager_loadings([@post, @post3], :association1)
|
|
84
84
|
UnusedEagerLoading.add_eager_loadings([@post, @post3], :association2)
|
|
@@ -89,7 +89,7 @@ module Bullet
|
|
|
89
89
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post3.bullet_key], :association2)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
it
|
|
92
|
+
it 'should delete objects, associations pair for existing eager_loadings' do
|
|
93
93
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
|
|
94
94
|
UnusedEagerLoading.add_eager_loadings([@post], :association2)
|
|
95
95
|
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Object do
|
|
4
|
-
context
|
|
5
|
-
it
|
|
4
|
+
context 'bullet_key' do
|
|
5
|
+
it 'should return class and id composition' do
|
|
6
6
|
post = Post.first
|
|
7
7
|
expect(post.bullet_key).to eq("Post:#{post.id}")
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
if mongoid?
|
|
11
|
-
it
|
|
11
|
+
it 'should return class with namesapce and id composition' do
|
|
12
12
|
post = Mongoid::Post.first
|
|
13
13
|
expect(post.bullet_key).to eq("Mongoid::Post:#{post.id}")
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
context
|
|
19
|
-
it
|
|
18
|
+
context 'primary_key_value' do
|
|
19
|
+
it 'should return id' do
|
|
20
20
|
post = Post.first
|
|
21
21
|
expect(post.primary_key_value).to eq(post.id)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
it
|
|
24
|
+
it 'should return primary key value' do
|
|
25
25
|
post = Post.first
|
|
26
26
|
Post.primary_key = 'name'
|
|
27
27
|
expect(post.primary_key_value).to eq(post.name)
|
|
28
28
|
Post.primary_key = 'id'
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
it
|
|
31
|
+
it 'should return value for multiple primary keys' do
|
|
32
32
|
post = Post.first
|
|
33
33
|
allow(Post).to receive(:primary_keys).and_return([:category_id, :writer_id])
|
|
34
34
|
expect(post.primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe String do
|
|
4
|
-
context
|
|
5
|
-
it
|
|
6
|
-
expect(
|
|
4
|
+
context 'bullet_class_name' do
|
|
5
|
+
it 'should only return class name' do
|
|
6
|
+
expect('Post:1'.bullet_class_name).to eq('Post')
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
it
|
|
10
|
-
expect(
|
|
9
|
+
it 'should return class name with namespace' do
|
|
10
|
+
expect('Mongoid::Post:1234567890'.bullet_class_name).to eq('Mongoid::Post')
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|