bullet 4.10.0 → 4.12.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 +21 -0
- data/Gemfile +4 -4
- data/Gemfile.mongoid-4.0 +1 -1
- data/Gemfile.rails-3.2 +1 -1
- data/Gemfile.rails-4.0 +1 -1
- data/Gemfile.rails-4.1 +1 -1
- data/README.md +52 -46
- data/bullet.gemspec +2 -2
- data/lib/bullet/active_record3.rb +7 -1
- data/lib/bullet/active_record3x.rb +7 -1
- data/lib/bullet/active_record4.rb +7 -11
- data/lib/bullet/active_record41.rb +7 -0
- data/lib/bullet/detector/association.rb +13 -5
- data/lib/bullet/detector/counter_cache.rb +12 -9
- data/lib/bullet/detector/n_plus_one_query.rb +29 -16
- data/lib/bullet/detector/unused_eager_loading.rb +16 -15
- data/lib/bullet/ext/object.rb +10 -2
- data/lib/bullet/notification/base.rb +5 -5
- data/lib/bullet/rack.rb +10 -4
- data/lib/bullet/registry/object.rb +4 -4
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +5 -2
- data/spec/bullet/detector/association_spec.rb +2 -2
- 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/detector/unused_eager_loading_spec.rb +15 -15
- data/spec/bullet/ext/object_spec.rb +17 -3
- data/spec/bullet/notification/base_spec.rb +37 -0
- data/spec/bullet/rack_spec.rb +2 -2
- data/spec/bullet/registry/object_spec.rb +4 -4
- data/spec/bullet_spec.rb +2 -2
- data/spec/integration/active_record3/association_spec.rb +12 -2
- data/spec/integration/active_record4/association_spec.rb +11 -1
- data/spec/models/category.rb +1 -1
- data/spec/models/post.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/bullet_ext.rb +1 -1
- metadata +6 -6
|
@@ -10,11 +10,13 @@ module Bullet
|
|
|
10
10
|
# if it is, keeps this unpreload associations and caller.
|
|
11
11
|
def call_association(object, associations)
|
|
12
12
|
return unless Bullet.start?
|
|
13
|
+
return unless object.primary_key_value
|
|
14
|
+
return if inversed_objects.include?(object.bullet_key, associations)
|
|
13
15
|
add_call_object_associations(object, associations)
|
|
14
16
|
|
|
15
|
-
Bullet.debug("Detector::NPlusOneQuery#call_association", "object: #{object.
|
|
16
|
-
if conditions_met?(object.
|
|
17
|
-
Bullet.debug("detect n + 1 query", "object: #{object.
|
|
17
|
+
Bullet.debug("Detector::NPlusOneQuery#call_association", "object: #{object.bullet_key}, associations: #{associations}")
|
|
18
|
+
if conditions_met?(object.bullet_key, associations)
|
|
19
|
+
Bullet.debug("detect n + 1 query", "object: #{object.bullet_key}, associations: #{associations}")
|
|
18
20
|
create_notification caller_in_project, object.class.to_s, associations
|
|
19
21
|
end
|
|
20
22
|
end
|
|
@@ -22,18 +24,29 @@ module Bullet
|
|
|
22
24
|
def add_possible_objects(object_or_objects)
|
|
23
25
|
return unless Bullet.start?
|
|
24
26
|
return unless Bullet.n_plus_one_query_enable?
|
|
25
|
-
|
|
26
27
|
objects = Array(object_or_objects)
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
return if objects.map(&:primary_key_value).compact.empty?
|
|
29
|
+
|
|
30
|
+
Bullet.debug("Detector::NPlusOneQuery#add_possible_objects", "objects: #{objects.map(&:bullet_key).join(', ')}")
|
|
31
|
+
objects.each { |object| possible_objects.add object.bullet_key }
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
def add_impossible_object(object)
|
|
32
35
|
return unless Bullet.start?
|
|
33
36
|
return unless Bullet.n_plus_one_query_enable?
|
|
37
|
+
return unless object.primary_key_value
|
|
38
|
+
|
|
39
|
+
Bullet.debug("Detector::NPlusOneQuery#add_impossible_object", "object: #{object.bullet_key}")
|
|
40
|
+
impossible_objects.add object.bullet_key
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def add_inversed_object(object, association)
|
|
44
|
+
return unless Bullet.start?
|
|
45
|
+
return unless Bullet.n_plus_one_query_enable?
|
|
46
|
+
return unless object.primary_key_value
|
|
34
47
|
|
|
35
|
-
Bullet.debug("Detector::NPlusOneQuery#
|
|
36
|
-
|
|
48
|
+
Bullet.debug("Detector::NPlusOneQuery#add_inversed_object", "object: #{object.bullet_key}, association: #{association}")
|
|
49
|
+
inversed_objects.add object.bullet_key, association
|
|
37
50
|
end
|
|
38
51
|
|
|
39
52
|
private
|
|
@@ -47,8 +60,8 @@ module Bullet
|
|
|
47
60
|
end
|
|
48
61
|
|
|
49
62
|
# decide whether the object.associations is unpreloaded or not.
|
|
50
|
-
def conditions_met?(
|
|
51
|
-
possible?(
|
|
63
|
+
def conditions_met?(bullet_key, associations)
|
|
64
|
+
possible?(bullet_key) && !impossible?(bullet_key) && !association?(bullet_key, associations)
|
|
52
65
|
end
|
|
53
66
|
|
|
54
67
|
def caller_in_project
|
|
@@ -60,17 +73,17 @@ module Bullet
|
|
|
60
73
|
end
|
|
61
74
|
end
|
|
62
75
|
|
|
63
|
-
def possible?(
|
|
64
|
-
possible_objects.include?
|
|
76
|
+
def possible?(bullet_key)
|
|
77
|
+
possible_objects.include? bullet_key
|
|
65
78
|
end
|
|
66
79
|
|
|
67
|
-
def impossible?(
|
|
68
|
-
impossible_objects.include?
|
|
80
|
+
def impossible?(bullet_key)
|
|
81
|
+
impossible_objects.include? bullet_key
|
|
69
82
|
end
|
|
70
83
|
|
|
71
84
|
# check if object => associations already exists in object_associations.
|
|
72
|
-
def association?(
|
|
73
|
-
value = object_associations[
|
|
85
|
+
def association?(bullet_key, associations)
|
|
86
|
+
value = object_associations[bullet_key]
|
|
74
87
|
if value
|
|
75
88
|
value.each do |v|
|
|
76
89
|
result = v.is_a?(Hash) ? v.has_key?(associations) : v == associations
|
|
@@ -10,26 +10,27 @@ module Bullet
|
|
|
10
10
|
return unless Bullet.start?
|
|
11
11
|
return unless Bullet.unused_eager_loading_enable?
|
|
12
12
|
|
|
13
|
-
object_associations.each do |
|
|
14
|
-
object_association_diff = diff_object_associations
|
|
13
|
+
object_associations.each do |bullet_key, associations|
|
|
14
|
+
object_association_diff = diff_object_associations bullet_key, associations
|
|
15
15
|
next if object_association_diff.empty?
|
|
16
16
|
|
|
17
|
-
Bullet.debug("detect unused preload", "object: #{
|
|
18
|
-
create_notification
|
|
17
|
+
Bullet.debug("detect unused preload", "object: #{bullet_key}, associations: #{object_association_diff}")
|
|
18
|
+
create_notification bullet_key.bullet_class_name, object_association_diff
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def add_eager_loadings(objects, associations)
|
|
23
23
|
return unless Bullet.start?
|
|
24
24
|
return unless Bullet.unused_eager_loading_enable?
|
|
25
|
+
return if objects.map(&:primary_key_value).compact.empty?
|
|
25
26
|
|
|
26
|
-
Bullet.debug("Detector::UnusedEagerLoading#add_eager_loadings", "objects: #{objects.map(&:
|
|
27
|
-
|
|
27
|
+
Bullet.debug("Detector::UnusedEagerLoading#add_eager_loadings", "objects: #{objects.map(&:bullet_key).join(', ')}, associations: #{associations}")
|
|
28
|
+
bullet_keys = objects.map(&:bullet_key)
|
|
28
29
|
|
|
29
30
|
to_add = nil
|
|
30
31
|
to_merge, to_delete = [], []
|
|
31
32
|
eager_loadings.each do |k, v|
|
|
32
|
-
key_objects_overlap = k &
|
|
33
|
+
key_objects_overlap = k & bullet_keys
|
|
33
34
|
|
|
34
35
|
next if key_objects_overlap.empty?
|
|
35
36
|
|
|
@@ -39,10 +40,10 @@ module Bullet
|
|
|
39
40
|
else
|
|
40
41
|
to_merge << [key_objects_overlap, ( eager_loadings[k].dup << associations )]
|
|
41
42
|
|
|
42
|
-
keys_without_objects = k -
|
|
43
|
+
keys_without_objects = k - bullet_keys
|
|
43
44
|
to_merge << [keys_without_objects, eager_loadings[k]]
|
|
44
45
|
to_delete << k
|
|
45
|
-
|
|
46
|
+
bullet_keys = bullet_keys - k
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
49
|
|
|
@@ -50,7 +51,7 @@ module Bullet
|
|
|
50
51
|
to_merge.each { |k,val| eager_loadings.merge k, val }
|
|
51
52
|
to_delete.each { |k| eager_loadings.delete k }
|
|
52
53
|
|
|
53
|
-
eager_loadings.add
|
|
54
|
+
eager_loadings.add bullet_keys, associations unless bullet_keys.empty?
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
private
|
|
@@ -63,18 +64,18 @@ module Bullet
|
|
|
63
64
|
end
|
|
64
65
|
end
|
|
65
66
|
|
|
66
|
-
def call_associations(
|
|
67
|
+
def call_associations(bullet_key, associations)
|
|
67
68
|
all = Set.new
|
|
68
|
-
eager_loadings.similarly_associated(
|
|
69
|
-
coa = call_object_associations[
|
|
69
|
+
eager_loadings.similarly_associated(bullet_key, associations).each do |related_bullet_key|
|
|
70
|
+
coa = call_object_associations[related_bullet_key]
|
|
70
71
|
next if coa.nil?
|
|
71
72
|
all.merge coa
|
|
72
73
|
end
|
|
73
74
|
all.to_a
|
|
74
75
|
end
|
|
75
76
|
|
|
76
|
-
def diff_object_associations(
|
|
77
|
-
potential_associations = associations - call_associations(
|
|
77
|
+
def diff_object_associations(bullet_key, associations)
|
|
78
|
+
potential_associations = associations - call_associations(bullet_key, associations)
|
|
78
79
|
potential_associations.reject { |a| a.is_a?(Hash) }
|
|
79
80
|
end
|
|
80
81
|
end
|
data/lib/bullet/ext/object.rb
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
class Object
|
|
2
|
-
def
|
|
3
|
-
|
|
2
|
+
def bullet_key
|
|
3
|
+
[self.class, self.primary_key_value].join(':')
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def primary_key_value
|
|
7
|
+
if self.class.respond_to?(:primary_key) && self.class.primary_key
|
|
8
|
+
self.send self.class.primary_key
|
|
9
|
+
else
|
|
10
|
+
self.id
|
|
11
|
+
end
|
|
4
12
|
end
|
|
5
13
|
end
|
|
@@ -19,9 +19,9 @@ module Bullet
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def whoami
|
|
22
|
-
user
|
|
23
|
-
if user
|
|
24
|
-
"user: #{user
|
|
22
|
+
@user ||= ENV['USER'].presence || (`whoami`.chomp rescue "")
|
|
23
|
+
if @user.present?
|
|
24
|
+
"user: #{@user}"
|
|
25
25
|
else
|
|
26
26
|
""
|
|
27
27
|
end
|
|
@@ -36,7 +36,7 @@ module Bullet
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def full_notice
|
|
39
|
-
[whoami, url, title, body_with_caller].compact.join("\n")
|
|
39
|
+
[whoami.presence, url, title, body_with_caller].compact.join("\n")
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def notify_inline
|
|
@@ -48,7 +48,7 @@ module Bullet
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def short_notice
|
|
51
|
-
[whoami, url, title, body].compact.join("\n")
|
|
51
|
+
[whoami.presence, url, title, body].compact.join("\n")
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def notification_data
|
data/lib/bullet/rack.rb
CHANGED
|
@@ -10,7 +10,7 @@ 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) || empty?(response)
|
|
13
|
+
return [status, headers, response] if file?(headers) || sse?(response) || empty?(response)
|
|
14
14
|
|
|
15
15
|
response_body = nil
|
|
16
16
|
if Bullet.notification?
|
|
@@ -19,10 +19,13 @@ module Bullet
|
|
|
19
19
|
add_footer_note(response_body) if Bullet.add_footer
|
|
20
20
|
headers['Content-Length'] = response_body.bytesize.to_s
|
|
21
21
|
end
|
|
22
|
+
end
|
|
23
|
+
[status, headers, response_body ? [response_body] : response]
|
|
24
|
+
ensure
|
|
25
|
+
if Bullet.enable? && Bullet.notification?
|
|
22
26
|
Bullet.perform_out_of_channel_notifications(env)
|
|
23
27
|
end
|
|
24
28
|
Bullet.end_request
|
|
25
|
-
[status, headers, response_body ? [response_body] : response]
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
# fix issue if response's body is a Proc
|
|
@@ -43,11 +46,14 @@ module Bullet
|
|
|
43
46
|
response_body << "<div #{footer_div_style}>" + Bullet.footer_info.uniq.join("<br>") + "</div>"
|
|
44
47
|
end
|
|
45
48
|
|
|
46
|
-
# if send file?
|
|
47
49
|
def file?(headers)
|
|
48
50
|
headers["Content-Transfer-Encoding"] == "binary"
|
|
49
51
|
end
|
|
50
52
|
|
|
53
|
+
def sse?(response)
|
|
54
|
+
response.respond_to?(:stream) && response.stream.is_a?(ActionController::Live::Buffer)
|
|
55
|
+
end
|
|
56
|
+
|
|
51
57
|
def html_request?(headers, response)
|
|
52
58
|
headers['Content-Type'] && headers['Content-Type'].include?('text/html') && response_body(response).include?("<html")
|
|
53
59
|
end
|
|
@@ -67,7 +73,7 @@ style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: s
|
|
|
67
73
|
-moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none;
|
|
68
74
|
-moz-border-left-colors: none; -moz-border-image: none; border-width: 2pt 2pt 0px 0px;
|
|
69
75
|
padding: 5px; border-radius: 0pt 10pt 0pt 0px; background: none repeat scroll 0% 0% rgba(200, 200, 200, 0.8);
|
|
70
|
-
color: rgb(119, 119, 119); font-size: 18px;"
|
|
76
|
+
color: rgb(119, 119, 119); font-size: 18px; font-family: 'Arial', sans-serif; z-index:9999;"
|
|
71
77
|
EOF
|
|
72
78
|
end
|
|
73
79
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module Bullet
|
|
2
2
|
module Registry
|
|
3
3
|
class Object < Base
|
|
4
|
-
def add(
|
|
5
|
-
super(
|
|
4
|
+
def add(bullet_key)
|
|
5
|
+
super(bullet_key.bullet_class_name, bullet_key)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
def include?(
|
|
9
|
-
super(
|
|
8
|
+
def include?(bullet_key)
|
|
9
|
+
super(bullet_key.bullet_class_name, bullet_key)
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
data/lib/bullet/version.rb
CHANGED
data/lib/bullet.rb
CHANGED
|
@@ -96,7 +96,7 @@ module Bullet
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
def debug(title, message)
|
|
99
|
-
puts "[Bullet][#{title}] #{message}" if ENV['
|
|
99
|
+
puts "[Bullet][#{title}] #{message}" if ENV['BULLET_DEBUG'] == 'true'
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
def start_request
|
|
@@ -107,6 +107,7 @@ module Bullet
|
|
|
107
107
|
Thread.current[:bullet_call_object_associations] = Bullet::Registry::Base.new
|
|
108
108
|
Thread.current[:bullet_possible_objects] = Bullet::Registry::Object.new
|
|
109
109
|
Thread.current[:bullet_impossible_objects] = Bullet::Registry::Object.new
|
|
110
|
+
Thread.current[:bullet_inversed_objects] = Bullet::Registry::Base.new
|
|
110
111
|
Thread.current[:bullet_eager_loadings] = Bullet::Registry::Association.new
|
|
111
112
|
|
|
112
113
|
Thread.current[:bullet_counter_possible_objects] ||= Bullet::Registry::Object.new
|
|
@@ -118,9 +119,10 @@ module Bullet
|
|
|
118
119
|
Thread.current[:bullet_notification_collector] = nil
|
|
119
120
|
|
|
120
121
|
Thread.current[:bullet_object_associations] = nil
|
|
122
|
+
Thread.current[:bullet_call_object_associations] = nil
|
|
121
123
|
Thread.current[:bullet_possible_objects] = nil
|
|
122
124
|
Thread.current[:bullet_impossible_objects] = nil
|
|
123
|
-
Thread.current[:
|
|
125
|
+
Thread.current[:bullet_inversed_objects] = nil
|
|
124
126
|
Thread.current[:bullet_eager_loadings] = nil
|
|
125
127
|
|
|
126
128
|
Thread.current[:bullet_counter_possible_objects] = nil
|
|
@@ -136,6 +138,7 @@ module Bullet
|
|
|
136
138
|
end
|
|
137
139
|
|
|
138
140
|
def notification?
|
|
141
|
+
return unless start?
|
|
139
142
|
Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
|
|
140
143
|
notification_collector.notifications_present?
|
|
141
144
|
end
|
|
@@ -11,14 +11,14 @@ module Bullet
|
|
|
11
11
|
context ".add_object_association" do
|
|
12
12
|
it "should add object, associations pair" do
|
|
13
13
|
Association.add_object_associations(@post1, :associations)
|
|
14
|
-
expect(Association.send(:object_associations)).to be_include(@post1.
|
|
14
|
+
expect(Association.send(:object_associations)).to be_include(@post1.bullet_key, :associations)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
context ".add_call_object_associations" do
|
|
19
19
|
it "should add call object, associations pair" do
|
|
20
20
|
Association.add_call_object_associations(@post1, :associations)
|
|
21
|
-
expect(Association.send(:call_object_associations)).to be_include(@post1.
|
|
21
|
+
expect(Association.send(:call_object_associations)).to be_include(@post1.bullet_key, :associations)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -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.bullet_key, [: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.bullet_key, [: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.send(:possible_objects)).to be_include(@post1.
|
|
29
|
-
expect(CounterCache.send(:possible_objects)).to be_include(@post2.
|
|
28
|
+
expect(CounterCache.send(:possible_objects)).to be_include(@post1.bullet_key)
|
|
29
|
+
expect(CounterCache.send(: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.send(:impossible_objects)).to be_include(@post1.
|
|
34
|
+
expect(CounterCache.send(: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.send(:conditions_met?, @post1.
|
|
41
|
+
expect(CounterCache.send(:conditions_met?, @post1.bullet_key, :associations)).to eq true
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
it "should be false when object is not possible" do
|
|
45
|
-
expect(CounterCache.send(:conditions_met?, @post1.
|
|
45
|
+
expect(CounterCache.send(:conditions_met?, @post1.bullet_key, :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.send(:conditions_met?, @post1.
|
|
51
|
+
expect(CounterCache.send(:conditions_met?, @post1.bullet_key, :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.send(:possible?, @post.
|
|
21
|
+
expect(NPlusOneQuery.send(:possible?, @post.bullet_key)).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.send(:impossible?, @post.
|
|
28
|
+
expect(NPlusOneQuery.send(:impossible?, @post.bullet_key)).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.send(:association?, @post.
|
|
35
|
+
expect(NPlusOneQuery.send(:association?, @post.bullet_key, :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.send(:association?, @post.
|
|
40
|
+
expect(NPlusOneQuery.send(:association?, @post.bullet_key, :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.send(:conditions_met?, @post.
|
|
46
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post.bullet_key).and_return(true)
|
|
47
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post.bullet_key).and_return(false)
|
|
48
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post.bullet_key, :associations).and_return(false)
|
|
49
|
+
expect(NPlusOneQuery.send(:conditions_met?, @post.bullet_key, :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.send(:conditions_met?, @post.
|
|
53
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post.bullet_key).and_return(false)
|
|
54
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post.bullet_key).and_return(false)
|
|
55
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post.bullet_key, :associations).and_return(false)
|
|
56
|
+
expect(NPlusOneQuery.send(:conditions_met?, @post.bullet_key, :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.send(:conditions_met?, @post.
|
|
60
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post.bullet_key).and_return(true)
|
|
61
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post.bullet_key).and_return(true)
|
|
62
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post.bullet_key, :associations).and_return(false)
|
|
63
|
+
expect(NPlusOneQuery.send(:conditions_met?, @post.bullet_key, :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.send(:conditions_met?, @post.
|
|
67
|
+
allow(NPlusOneQuery).to receive(:possible?).with(@post.bullet_key).and_return(true)
|
|
68
|
+
allow(NPlusOneQuery).to receive(:impossible?).with(@post.bullet_key).and_return(false)
|
|
69
|
+
allow(NPlusOneQuery).to receive(:association?).with(@post.bullet_key, :associations).and_return(true)
|
|
70
|
+
expect(NPlusOneQuery.send(:conditions_met?, @post.bullet_key, :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.bullet_key, :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.bullet_key, :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.bullet_key, :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.bullet_key, :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.send(:possible_objects)).to be_include(@post.
|
|
122
|
-
expect(NPlusOneQuery.send(:possible_objects)).to be_include(@post2.
|
|
121
|
+
expect(NPlusOneQuery.send(:possible_objects)).to be_include(@post.bullet_key)
|
|
122
|
+
expect(NPlusOneQuery.send(: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.send(:impossible_objects)).to be_include(@post.
|
|
133
|
+
expect(NPlusOneQuery.send(:impossible_objects)).to be_include(@post.bullet_key)
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
end
|
|
@@ -10,30 +10,30 @@ module Bullet
|
|
|
10
10
|
|
|
11
11
|
context ".call_associations" do
|
|
12
12
|
it "should get empty array if eager_loadings" do
|
|
13
|
-
expect(UnusedEagerLoading.send(:call_associations, @post.
|
|
13
|
+
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
it "should get call associations if object and association are both in eager_loadings and call_object_associations" do
|
|
17
17
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
|
18
18
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
|
19
|
-
expect(UnusedEagerLoading.send(:call_associations, @post.
|
|
19
|
+
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to eq([:association])
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
it "should not get call associations if not exist in call_object_associations" do
|
|
23
23
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
|
24
|
-
expect(UnusedEagerLoading.send(:call_associations, @post.
|
|
24
|
+
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
context ".diff_object_associations" do
|
|
29
29
|
it "should return associations not exist in call_association" do
|
|
30
|
-
expect(UnusedEagerLoading.send(:diff_object_associations, @post.
|
|
30
|
+
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to eq([:association])
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
it "should return empty if associations exist in call_association" do
|
|
34
34
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
|
35
35
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
|
36
|
-
expect(UnusedEagerLoading.send(:diff_object_associations, @post.
|
|
36
|
+
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
@@ -48,7 +48,7 @@ module Bullet
|
|
|
48
48
|
UnusedEagerLoading.add_object_associations(@post, :association)
|
|
49
49
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
|
50
50
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
|
51
|
-
expect(UnusedEagerLoading.send(:diff_object_associations, @post.
|
|
51
|
+
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to be_empty
|
|
52
52
|
expect(UnusedEagerLoading).not_to receive(:create_notification).with("Post", [:association])
|
|
53
53
|
UnusedEagerLoading.check_unused_preload_associations
|
|
54
54
|
end
|
|
@@ -57,30 +57,30 @@ module Bullet
|
|
|
57
57
|
context ".add_eager_loadings" do
|
|
58
58
|
it "should add objects, associations pair when eager_loadings are empty" do
|
|
59
59
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :associations)
|
|
60
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.
|
|
60
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :associations)
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
it "should add objects, associations pair for existing eager_loadings" do
|
|
64
64
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
|
|
65
65
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
|
|
66
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.
|
|
67
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.
|
|
66
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :association1)
|
|
67
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :association2)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
it "should merge objects, associations pair for existing eager_loadings" do
|
|
71
71
|
UnusedEagerLoading.add_eager_loadings([@post], :association1)
|
|
72
72
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
|
|
73
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.
|
|
74
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.
|
|
75
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.
|
|
73
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
|
|
74
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
|
|
75
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key, @post2.bullet_key], :association2)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
it "should delete objects, associations pair for existing eager_loadings" do
|
|
79
79
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
|
|
80
80
|
UnusedEagerLoading.add_eager_loadings([@post], :association2)
|
|
81
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.
|
|
82
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.
|
|
83
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.
|
|
81
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association1)
|
|
82
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post.bullet_key], :association2)
|
|
83
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include([@post2.bullet_key], :association1)
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
end
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Object do
|
|
4
|
-
context "
|
|
4
|
+
context "bullet_key" do
|
|
5
5
|
it "should return class and id composition" do
|
|
6
6
|
post = Post.first
|
|
7
|
-
expect(post.
|
|
7
|
+
expect(post.bullet_key).to eq("Post:#{post.id}")
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
if mongoid?
|
|
11
11
|
it "should return class with namesapce and id composition" do
|
|
12
12
|
post = Mongoid::Post.first
|
|
13
|
-
expect(post.
|
|
13
|
+
expect(post.bullet_key).to eq("Mongoid::Post:#{post.id}")
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
context "primary_key_value" do
|
|
19
|
+
it "should return id" do
|
|
20
|
+
post = Post.first
|
|
21
|
+
expect(post.primary_key_value).to eq(post.id)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should return primary key value" do
|
|
25
|
+
post = Post.first
|
|
26
|
+
Post.primary_key = 'name'
|
|
27
|
+
expect(post.primary_key_value).to eq(post.name)
|
|
28
|
+
Post.primary_key = 'id'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
17
31
|
end
|