bullet 4.14.5 → 4.14.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile.mongoid-5.0 +17 -0
- data/README.md +21 -0
- data/lib/bullet/active_record3.rb +65 -35
- data/lib/bullet/active_record3x.rb +54 -32
- data/lib/bullet/active_record4.rb +61 -31
- data/lib/bullet/active_record41.rb +62 -32
- data/lib/bullet/active_record42.rb +93 -49
- data/lib/bullet/dependency.rb +6 -0
- data/lib/bullet/detector/association.rb +16 -16
- data/lib/bullet/detector/counter_cache.rb +13 -13
- data/lib/bullet/detector/n_plus_one_query.rb +30 -30
- data/lib/bullet/detector/unused_eager_loading.rb +1 -1
- data/lib/bullet/ext/object.rb +3 -1
- data/lib/bullet/mongoid5x.rb +56 -0
- data/lib/bullet/rack.rb +2 -2
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +14 -4
- data/spec/bullet/detector/counter_cache_spec.rb +8 -8
- data/spec/bullet/detector/n_plus_one_query_spec.rb +27 -27
- data/spec/bullet/ext/object_spec.rb +6 -0
- data/spec/bullet/notification/base_spec.rb +2 -2
- data/spec/bullet_spec.rb +47 -0
- data/spec/integration/active_record3/association_spec.rb +11 -2
- data/spec/integration/active_record4/association_spec.rb +32 -2
- data/spec/integration/counter_cache_spec.rb +8 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/support/mongo_seed.rb +13 -0
- data/test.sh +1 -0
- data/update.sh +1 -0
- metadata +5 -3
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Bullet
|
|
2
|
+
module Mongoid
|
|
3
|
+
def self.enable
|
|
4
|
+
require 'mongoid'
|
|
5
|
+
::Mongoid::Contextual::Mongo.class_eval do
|
|
6
|
+
alias_method :origin_first, :first
|
|
7
|
+
alias_method :origin_last, :last
|
|
8
|
+
alias_method :origin_each, :each
|
|
9
|
+
alias_method :origin_eager_load, :eager_load
|
|
10
|
+
|
|
11
|
+
def first
|
|
12
|
+
result = origin_first
|
|
13
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
|
14
|
+
result
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def last
|
|
18
|
+
result = origin_last
|
|
19
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
|
20
|
+
result
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def each(&block)
|
|
24
|
+
records = view.map{ |doc| ::Mongoid::Factory.from_db(klass, doc) }
|
|
25
|
+
if records.length > 1
|
|
26
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
27
|
+
elsif records.size == 1
|
|
28
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
29
|
+
end
|
|
30
|
+
origin_each(&block)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def eager_load(docs)
|
|
34
|
+
associations = criteria.inclusions.map(&:name)
|
|
35
|
+
docs.each do |doc|
|
|
36
|
+
Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations)
|
|
37
|
+
end
|
|
38
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
|
|
39
|
+
origin_eager_load(docs)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
::Mongoid::Relations::Accessors.class_eval do
|
|
44
|
+
alias_method :origin_get_relation, :get_relation
|
|
45
|
+
|
|
46
|
+
def get_relation(name, metadata, object, reload = false)
|
|
47
|
+
result = origin_get_relation(name, metadata, object, reload)
|
|
48
|
+
if metadata.macro !~ /embed/
|
|
49
|
+
Bullet::Detector::NPlusOneQuery.call_association(self, name)
|
|
50
|
+
end
|
|
51
|
+
result
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/bullet/rack.rb
CHANGED
|
@@ -10,11 +10,11 @@ module Bullet
|
|
|
10
10
|
return @app.call(env) unless Bullet.enable?
|
|
11
11
|
Bullet.start_request
|
|
12
12
|
status, headers, response = @app.call(env)
|
|
13
|
-
return [status, headers, response] if file?(headers) || sse?(headers) || empty?(response)
|
|
14
13
|
|
|
15
14
|
response_body = nil
|
|
16
15
|
if Bullet.notification?
|
|
17
|
-
if
|
|
16
|
+
if !file?(headers) && !sse?(headers) && !empty?(response) &&
|
|
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)
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
|
@@ -16,6 +16,9 @@ module Bullet
|
|
|
16
16
|
autoload :Registry, 'bullet/registry'
|
|
17
17
|
autoload :NotificationCollector, 'bullet/notification_collector'
|
|
18
18
|
|
|
19
|
+
BULLET_DEBUG = 'BULLET_DEBUG'.freeze
|
|
20
|
+
TRUE = 'true'.freeze
|
|
21
|
+
|
|
19
22
|
if defined? Rails::Railtie
|
|
20
23
|
class BulletRailtie < Rails::Railtie
|
|
21
24
|
initializer "bullet.configure_rails_initialization" do |app|
|
|
@@ -29,7 +32,9 @@ module Bullet
|
|
|
29
32
|
attr_reader :notification_collector, :whitelist
|
|
30
33
|
attr_accessor :add_footer, :orm_pathches_applied
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
available_notifiers = UniformNotifier::AVAILABLE_NOTIFIERS.map { |notifier| "#{notifier}=" }
|
|
36
|
+
available_notifiers << { :to => UniformNotifier }
|
|
37
|
+
delegate *available_notifiers
|
|
33
38
|
|
|
34
39
|
def raise=(should_raise)
|
|
35
40
|
UniformNotifier.raise=(should_raise ? Notification::UnoptimizedQueryError : false)
|
|
@@ -72,6 +77,7 @@ module Bullet
|
|
|
72
77
|
end
|
|
73
78
|
|
|
74
79
|
def add_whitelist(options)
|
|
80
|
+
reset_whitelist
|
|
75
81
|
@whitelist[options[:type]][options[:class_name].classify] ||= []
|
|
76
82
|
@whitelist[options[:type]][options[:class_name].classify] << options[:association].to_sym
|
|
77
83
|
end
|
|
@@ -81,7 +87,11 @@ module Bullet
|
|
|
81
87
|
end
|
|
82
88
|
|
|
83
89
|
def reset_whitelist
|
|
84
|
-
@whitelist
|
|
90
|
+
@whitelist ||= {:n_plus_one_query => {}, :unused_eager_loading => {}, :counter_cache => {}}
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def clear_whitelist
|
|
94
|
+
@whitelist = nil
|
|
85
95
|
end
|
|
86
96
|
|
|
87
97
|
def bullet_logger=(active)
|
|
@@ -96,7 +106,7 @@ module Bullet
|
|
|
96
106
|
end
|
|
97
107
|
|
|
98
108
|
def debug(title, message)
|
|
99
|
-
puts "[Bullet][#{title}] #{message}" if ENV[
|
|
109
|
+
puts "[Bullet][#{title}] #{message}" if ENV[BULLET_DEBUG] == TRUE
|
|
100
110
|
end
|
|
101
111
|
|
|
102
112
|
def start_request
|
|
@@ -130,7 +140,7 @@ module Bullet
|
|
|
130
140
|
end
|
|
131
141
|
|
|
132
142
|
def start?
|
|
133
|
-
Thread.current[:bullet_start]
|
|
143
|
+
enable? && Thread.current[:bullet_start]
|
|
134
144
|
end
|
|
135
145
|
|
|
136
146
|
def notification_collector
|
|
@@ -10,13 +10,13 @@ module Bullet
|
|
|
10
10
|
|
|
11
11
|
context ".add_counter_cache" do
|
|
12
12
|
it "should create notification if conditions met" do
|
|
13
|
-
expect(CounterCache).to receive(:conditions_met?).with(@post1
|
|
13
|
+
expect(CounterCache).to receive(:conditions_met?).with(@post1, [:comments]).and_return(true)
|
|
14
14
|
expect(CounterCache).to receive(:create_notification).with("Post", [:comments])
|
|
15
15
|
CounterCache.add_counter_cache(@post1, [:comments])
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
it "should not create notification if conditions not met" do
|
|
19
|
-
expect(CounterCache).to receive(:conditions_met?).with(@post1
|
|
19
|
+
expect(CounterCache).to receive(:conditions_met?).with(@post1, [:comments]).and_return(false)
|
|
20
20
|
expect(CounterCache).to receive(:create_notification).never
|
|
21
21
|
CounterCache.add_counter_cache(@post1, [:comments])
|
|
22
22
|
end
|
|
@@ -25,30 +25,30 @@ module Bullet
|
|
|
25
25
|
context ".add_possible_objects" do
|
|
26
26
|
it "should add possible objects" do
|
|
27
27
|
CounterCache.add_possible_objects([@post1, @post2])
|
|
28
|
-
expect(CounterCache.
|
|
29
|
-
expect(CounterCache.
|
|
28
|
+
expect(CounterCache.possible_objects).to be_include(@post1.bullet_key)
|
|
29
|
+
expect(CounterCache.possible_objects).to be_include(@post2.bullet_key)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "should add impossible object" do
|
|
33
33
|
CounterCache.add_impossible_object(@post1)
|
|
34
|
-
expect(CounterCache.
|
|
34
|
+
expect(CounterCache.impossible_objects).to be_include(@post1.bullet_key)
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
context ".conditions_met?" do
|
|
39
39
|
it "should be true when object is possible, not impossible" do
|
|
40
40
|
CounterCache.add_possible_objects(@post1)
|
|
41
|
-
expect(CounterCache.
|
|
41
|
+
expect(CounterCache.conditions_met?(@post1, :associations)).to eq true
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
it "should be false when object is not possible" do
|
|
45
|
-
expect(CounterCache.
|
|
45
|
+
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
it "should be true when object is possible, and impossible" do
|
|
49
49
|
CounterCache.add_possible_objects(@post1)
|
|
50
50
|
CounterCache.add_impossible_object(@post1)
|
|
51
|
-
expect(CounterCache.
|
|
51
|
+
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
end
|
|
@@ -18,69 +18,69 @@ module Bullet
|
|
|
18
18
|
context ".possible?" do
|
|
19
19
|
it "should be true if possible_objects contain" do
|
|
20
20
|
NPlusOneQuery.add_possible_objects(@post)
|
|
21
|
-
expect(NPlusOneQuery.
|
|
21
|
+
expect(NPlusOneQuery.possible?(@post)).to eq true
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
context ".impossible?" do
|
|
26
26
|
it "should be true if impossible_objects contain" do
|
|
27
27
|
NPlusOneQuery.add_impossible_object(@post)
|
|
28
|
-
expect(NPlusOneQuery.
|
|
28
|
+
expect(NPlusOneQuery.impossible?(@post)).to eq true
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
context ".association?" do
|
|
33
33
|
it "should be true if object, associations pair is already existed" do
|
|
34
34
|
NPlusOneQuery.add_object_associations(@post, :association)
|
|
35
|
-
expect(NPlusOneQuery.
|
|
35
|
+
expect(NPlusOneQuery.association?(@post, :association)).to eq true
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
it "should be false if object, association pair is not existed" do
|
|
39
39
|
NPlusOneQuery.add_object_associations(@post, :association1)
|
|
40
|
-
expect(NPlusOneQuery.
|
|
40
|
+
expect(NPlusOneQuery.association?(@post, :associatio2)).to eq false
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
context ".conditions_met?" do
|
|
45
45
|
it "should be true if object is possible, not impossible and object, associations pair is not already existed" do
|
|
46
|
-
allow(NPlusOneQuery).to receive(:possible?).with(@post
|
|
47
|
-
allow(NPlusOneQuery).to receive(:impossible?).with(@post
|
|
48
|
-
allow(NPlusOneQuery).to receive(:association?).with(@post
|
|
49
|
-
expect(NPlusOneQuery.
|
|
46
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
|
47
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
|
48
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
|
49
|
+
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq true
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
it "should be false if object is not possible, not impossible and object, associations pair is not already existed" do
|
|
53
|
-
allow(NPlusOneQuery).to receive(:possible?).with(@post
|
|
54
|
-
allow(NPlusOneQuery).to receive(:impossible?).with(@post
|
|
55
|
-
allow(NPlusOneQuery).to receive(:association?).with(@post
|
|
56
|
-
expect(NPlusOneQuery.
|
|
53
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(false)
|
|
54
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
|
55
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
|
56
|
+
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
it "should be false if object is possible, but impossible and object, associations pair is not already existed" do
|
|
60
|
-
allow(NPlusOneQuery).to receive(:possible?).with(@post
|
|
61
|
-
allow(NPlusOneQuery).to receive(:impossible?).with(@post
|
|
62
|
-
allow(NPlusOneQuery).to receive(:association?).with(@post
|
|
63
|
-
expect(NPlusOneQuery.
|
|
60
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
|
61
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(true)
|
|
62
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(false)
|
|
63
|
+
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
it "should be false if object is possible, not impossible and object, associations pair is already existed" do
|
|
67
|
-
allow(NPlusOneQuery).to receive(:possible?).with(@post
|
|
68
|
-
allow(NPlusOneQuery).to receive(:impossible?).with(@post
|
|
69
|
-
allow(NPlusOneQuery).to receive(:association?).with(@post
|
|
70
|
-
expect(NPlusOneQuery.
|
|
67
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post).and_return(true)
|
|
68
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post).and_return(false)
|
|
69
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post, :associations).and_return(true)
|
|
70
|
+
expect(NPlusOneQuery.conditions_met?(@post, :associations)).to eq false
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
context ".call_association" do
|
|
75
75
|
it "should create notification if conditions met" do
|
|
76
|
-
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post
|
|
76
|
+
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
|
77
77
|
expect(NPlusOneQuery).to receive(:caller_in_project).and_return(["caller"])
|
|
78
78
|
expect(NPlusOneQuery).to receive(:create_notification).with(["caller"], "Post", :association)
|
|
79
79
|
NPlusOneQuery.call_association(@post, :association)
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
it "should not create notification if conditions not met" do
|
|
83
|
-
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post
|
|
83
|
+
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(false)
|
|
84
84
|
expect(NPlusOneQuery).not_to receive(:caller_in_project!)
|
|
85
85
|
expect(NPlusOneQuery).not_to receive(:create_notification).with("Post", :association)
|
|
86
86
|
NPlusOneQuery.call_association(@post, :association)
|
|
@@ -93,7 +93,7 @@ module Bullet
|
|
|
93
93
|
not_in_project = '/def/def.rb'
|
|
94
94
|
|
|
95
95
|
expect(NPlusOneQuery).to receive(:caller).and_return([in_project, not_in_project])
|
|
96
|
-
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post
|
|
96
|
+
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
|
97
97
|
expect(NPlusOneQuery).to receive(:create_notification).with([in_project], "Post", :association)
|
|
98
98
|
NPlusOneQuery.call_association(@post, :association)
|
|
99
99
|
end
|
|
@@ -108,7 +108,7 @@ module Bullet
|
|
|
108
108
|
excluded_gem = '/ghi/ghi.rb'
|
|
109
109
|
|
|
110
110
|
expect(NPlusOneQuery).to receive(:caller).and_return([in_project, included_gem, excluded_gem])
|
|
111
|
-
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post
|
|
111
|
+
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
|
112
112
|
expect(NPlusOneQuery).to receive(:create_notification).with([in_project, included_gem], "Post", :association)
|
|
113
113
|
NPlusOneQuery.call_association(@post, :association)
|
|
114
114
|
end
|
|
@@ -118,8 +118,8 @@ module Bullet
|
|
|
118
118
|
context ".add_possible_objects" do
|
|
119
119
|
it "should add possible objects" do
|
|
120
120
|
NPlusOneQuery.add_possible_objects([@post, @post2])
|
|
121
|
-
expect(NPlusOneQuery.
|
|
122
|
-
expect(NPlusOneQuery.
|
|
121
|
+
expect(NPlusOneQuery.possible_objects).to be_include(@post.bullet_key)
|
|
122
|
+
expect(NPlusOneQuery.possible_objects).to be_include(@post2.bullet_key)
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
it "should not raise error if object is nil" do
|
|
@@ -130,7 +130,7 @@ module Bullet
|
|
|
130
130
|
context ".add_impossible_object" do
|
|
131
131
|
it "should add impossible object" do
|
|
132
132
|
NPlusOneQuery.add_impossible_object(@post)
|
|
133
|
-
expect(NPlusOneQuery.
|
|
133
|
+
expect(NPlusOneQuery.impossible_objects).to be_include(@post.bullet_key)
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
end
|
|
@@ -27,5 +27,11 @@ describe Object do
|
|
|
27
27
|
expect(post.primary_key_value).to eq(post.name)
|
|
28
28
|
Post.primary_key = 'id'
|
|
29
29
|
end
|
|
30
|
+
|
|
31
|
+
it "should return value for multiple primary keys" do
|
|
32
|
+
post = Post.first
|
|
33
|
+
allow(Post).to receive(:primary_keys).and_return([:category_id, :writer_id])
|
|
34
|
+
expect(post.primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
|
|
35
|
+
end
|
|
30
36
|
end
|
|
31
37
|
end
|
|
@@ -30,14 +30,14 @@ module Bullet
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "should return blank if no user available" do
|
|
33
|
-
temp_env_variable("USER","") do
|
|
33
|
+
temp_env_variable("USER", "") do
|
|
34
34
|
expect(subject).to receive(:`).with("whoami").and_return("")
|
|
35
35
|
expect(subject.whoami).to eq("")
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
it "should return blank if whoami is not available" do
|
|
40
|
-
temp_env_variable("USER","") do
|
|
40
|
+
temp_env_variable("USER", "") do
|
|
41
41
|
expect(subject).to receive(:`).with("whoami").and_raise(Errno::ENOENT)
|
|
42
42
|
expect(subject.whoami).to eq("")
|
|
43
43
|
end
|
data/spec/bullet_spec.rb
CHANGED
|
@@ -38,4 +38,51 @@ describe Bullet, focused: true do
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
describe '#start?' do
|
|
43
|
+
context 'when bullet is disabled' do
|
|
44
|
+
before(:each) do
|
|
45
|
+
Bullet.enable = false
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'should not be started' do
|
|
49
|
+
expect(Bullet).not_to be_start
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe '#debug' do
|
|
55
|
+
before(:each) do
|
|
56
|
+
$stdout = StringIO.new
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
after(:each) do
|
|
60
|
+
$stdout = STDOUT
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'when debug is enabled' do
|
|
64
|
+
before(:each) do
|
|
65
|
+
ENV['BULLET_DEBUG'] = 'true'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
after(:each) do
|
|
69
|
+
ENV['BULLET_DEBUG'] = 'false'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should output debug information' do
|
|
73
|
+
Bullet.debug('debug_message', 'this is helpful information')
|
|
74
|
+
|
|
75
|
+
expect($stdout.string)
|
|
76
|
+
.to eq("[Bullet][debug_message] this is helpful information\n")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context 'when debug is disabled' do
|
|
81
|
+
it 'should output debug information' do
|
|
82
|
+
Bullet.debug('debug_message', 'this is helpful information')
|
|
83
|
+
|
|
84
|
+
expect($stdout.string).to be_empty
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
41
88
|
end
|
|
@@ -335,6 +335,15 @@ if !mongoid? && active_record3?
|
|
|
335
335
|
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
|
|
336
336
|
end
|
|
337
337
|
|
|
338
|
+
it "should not detect non preload association with only one comment" do
|
|
339
|
+
Comment.first.post.category.name
|
|
340
|
+
|
|
341
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
342
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
343
|
+
|
|
344
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
345
|
+
end
|
|
346
|
+
|
|
338
347
|
it "should detect non preload association with post => category" do
|
|
339
348
|
Comment.includes(:post).each do |comment|
|
|
340
349
|
comment.post.category.name
|
|
@@ -615,7 +624,7 @@ if !mongoid? && active_record3?
|
|
|
615
624
|
|
|
616
625
|
context "whitelist n plus one query" do
|
|
617
626
|
before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
|
|
618
|
-
after { Bullet.
|
|
627
|
+
after { Bullet.clear_whitelist }
|
|
619
628
|
|
|
620
629
|
it "should not detect n plus one query" do
|
|
621
630
|
Post.all.each do |post|
|
|
@@ -638,7 +647,7 @@ if !mongoid? && active_record3?
|
|
|
638
647
|
|
|
639
648
|
context "whitelist unused eager loading" do
|
|
640
649
|
before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
|
|
641
|
-
after { Bullet.
|
|
650
|
+
after { Bullet.clear_whitelist }
|
|
642
651
|
|
|
643
652
|
it "should not detect unused eager loading" do
|
|
644
653
|
Post.includes(:comments).map(&:name)
|
|
@@ -347,6 +347,15 @@ if !mongoid? && active_record4?
|
|
|
347
347
|
expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
|
|
348
348
|
end
|
|
349
349
|
|
|
350
|
+
it "should not detect non preload association with only one comment" do
|
|
351
|
+
Comment.first.post.category.name
|
|
352
|
+
|
|
353
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
354
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
355
|
+
|
|
356
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
357
|
+
end
|
|
358
|
+
|
|
350
359
|
it "should detect non preload association with post => category" do
|
|
351
360
|
Comment.includes(:post).each do |comment|
|
|
352
361
|
comment.post.category.name
|
|
@@ -551,6 +560,27 @@ if !mongoid? && active_record4?
|
|
|
551
560
|
end
|
|
552
561
|
end
|
|
553
562
|
|
|
563
|
+
describe Bullet::Detector::Association, "query immediately after creation" do
|
|
564
|
+
context "document => children" do
|
|
565
|
+
it 'should not detect non preload associations' do
|
|
566
|
+
document1 = Document.new
|
|
567
|
+
document1.children.build
|
|
568
|
+
document1.save
|
|
569
|
+
|
|
570
|
+
document2 = Document.new(parent: document1)
|
|
571
|
+
document2.save
|
|
572
|
+
document2.parent
|
|
573
|
+
|
|
574
|
+
document1.children.each.first
|
|
575
|
+
|
|
576
|
+
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
577
|
+
expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
|
|
578
|
+
|
|
579
|
+
expect(Bullet::Detector::Association).to be_completely_preloading_associations
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
554
584
|
describe Bullet::Detector::Association, "STI" do
|
|
555
585
|
context "page => author" do
|
|
556
586
|
it "should detect non preload associations" do
|
|
@@ -638,7 +668,7 @@ if !mongoid? && active_record4?
|
|
|
638
668
|
|
|
639
669
|
context "whitelist n plus one query" do
|
|
640
670
|
before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
|
|
641
|
-
after { Bullet.
|
|
671
|
+
after { Bullet.clear_whitelist }
|
|
642
672
|
|
|
643
673
|
it "should not detect n plus one query" do
|
|
644
674
|
Post.all.each do |post|
|
|
@@ -661,7 +691,7 @@ if !mongoid? && active_record4?
|
|
|
661
691
|
|
|
662
692
|
context "whitelist unused eager loading" do
|
|
663
693
|
before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
|
|
664
|
-
after { Bullet.
|
|
694
|
+
after { Bullet.clear_whitelist }
|
|
665
695
|
|
|
666
696
|
it "should not detect unused eager loading" do
|
|
667
697
|
Post.includes(:comments).map(&:name)
|
|
@@ -29,6 +29,13 @@ if !mongoid? && active_record?
|
|
|
29
29
|
expect(Bullet.collected_counter_cache_notifications).to be_empty
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
it "should need counter cache for has_many through" do
|
|
33
|
+
Client.all.each do |client|
|
|
34
|
+
client.firms.size
|
|
35
|
+
end
|
|
36
|
+
expect(Bullet.collected_counter_cache_notifications).not_to be_empty
|
|
37
|
+
end
|
|
38
|
+
|
|
32
39
|
it "should not need counter cache with part of cities" do
|
|
33
40
|
Country.all.each do |country|
|
|
34
41
|
country.cities.where(:name => 'first').size
|
|
@@ -50,7 +57,7 @@ if !mongoid? && active_record?
|
|
|
50
57
|
|
|
51
58
|
context "whitelist" do
|
|
52
59
|
before { Bullet.add_whitelist :type => :counter_cache, :class_name => "Country", :association => :cities }
|
|
53
|
-
after { Bullet.
|
|
60
|
+
after { Bullet.clear_whitelist }
|
|
54
61
|
|
|
55
62
|
it "should not detect counter cache" do
|
|
56
63
|
Country.all.each do |country|
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/mongo_seed.rb
CHANGED
|
@@ -52,6 +52,19 @@ module Support
|
|
|
52
52
|
}
|
|
53
53
|
)
|
|
54
54
|
end
|
|
55
|
+
elsif Mongoid::VERSION =~ /\A5/
|
|
56
|
+
Mongoid.configure do |config|
|
|
57
|
+
config.load_configuration(
|
|
58
|
+
clients: {
|
|
59
|
+
default: {
|
|
60
|
+
database: "bullet",
|
|
61
|
+
hosts: [ "localhost:27017" ]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
# Increase the level from DEBUG in order to avoid excessive logging to the screen
|
|
67
|
+
Mongo::Logger.logger.level = Logger::WARN
|
|
55
68
|
end
|
|
56
69
|
end
|
|
57
70
|
|
data/test.sh
CHANGED
|
@@ -6,6 +6,7 @@ BUNDLE_GEMFILE=Gemfile.rails-4.0 bundle && BUNDLE_GEMFILE=Gemfile.rails-4.0 bund
|
|
|
6
6
|
BUNDLE_GEMFILE=Gemfile.rails-3.2 bundle && BUNDLE_GEMFILE=Gemfile.rails-3.2 bundle exec rspec spec
|
|
7
7
|
BUNDLE_GEMFILE=Gemfile.rails-3.1 bundle && BUNDLE_GEMFILE=Gemfile.rails-3.1 bundle exec rspec spec
|
|
8
8
|
BUNDLE_GEMFILE=Gemfile.rails-3.0 bundle && BUNDLE_GEMFILE=Gemfile.rails-3.0 bundle exec rspec spec
|
|
9
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-5.0 bundle && BUNDLE_GEMFILE=Gemfile.mongoid-5.0 bundle exec rspec spec
|
|
9
10
|
BUNDLE_GEMFILE=Gemfile.mongoid-4.0 bundle && BUNDLE_GEMFILE=Gemfile.mongoid-4.0 bundle exec rspec spec
|
|
10
11
|
BUNDLE_GEMFILE=Gemfile.mongoid-3.1 bundle && BUNDLE_GEMFILE=Gemfile.mongoid-3.1 bundle exec rspec spec
|
|
11
12
|
BUNDLE_GEMFILE=Gemfile.mongoid-3.0 bundle && BUNDLE_GEMFILE=Gemfile.mongoid-3.0 bundle exec rspec spec
|
data/update.sh
CHANGED
|
@@ -4,6 +4,7 @@ BUNDLE_GEMFILE=Gemfile.rails-4.0 bundle update
|
|
|
4
4
|
BUNDLE_GEMFILE=Gemfile.rails-3.2 bundle update
|
|
5
5
|
BUNDLE_GEMFILE=Gemfile.rails-3.1 bundle update
|
|
6
6
|
BUNDLE_GEMFILE=Gemfile.rails-3.0 bundle update
|
|
7
|
+
BUNDLE_GEMFILE=Gemfile.mongoid-5.0 bundle update
|
|
7
8
|
BUNDLE_GEMFILE=Gemfile.mongoid-4.0 bundle update
|
|
8
9
|
BUNDLE_GEMFILE=Gemfile.mongoid-3.1 bundle update
|
|
9
10
|
BUNDLE_GEMFILE=Gemfile.mongoid-3.0 bundle update
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bullet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.14.
|
|
4
|
+
version: 4.14.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Richard Huang
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-10-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -59,6 +59,7 @@ files:
|
|
|
59
59
|
- Gemfile.mongoid-3.0
|
|
60
60
|
- Gemfile.mongoid-3.1
|
|
61
61
|
- Gemfile.mongoid-4.0
|
|
62
|
+
- Gemfile.mongoid-5.0
|
|
62
63
|
- Gemfile.rails-3.0
|
|
63
64
|
- Gemfile.rails-3.1
|
|
64
65
|
- Gemfile.rails-3.2
|
|
@@ -89,6 +90,7 @@ files:
|
|
|
89
90
|
- lib/bullet/mongoid2x.rb
|
|
90
91
|
- lib/bullet/mongoid3x.rb
|
|
91
92
|
- lib/bullet/mongoid4x.rb
|
|
93
|
+
- lib/bullet/mongoid5x.rb
|
|
92
94
|
- lib/bullet/notification.rb
|
|
93
95
|
- lib/bullet/notification/base.rb
|
|
94
96
|
- lib/bullet/notification/counter_cache.rb
|
|
@@ -184,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
184
186
|
version: 1.3.6
|
|
185
187
|
requirements: []
|
|
186
188
|
rubyforge_project:
|
|
187
|
-
rubygems_version: 2.4.
|
|
189
|
+
rubygems_version: 2.4.6
|
|
188
190
|
signing_key:
|
|
189
191
|
specification_version: 4
|
|
190
192
|
summary: help to kill N+1 queries and unused eager loading.
|