bullet_instructure 4.0.5 → 4.14.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +27 -1
  3. data/CHANGELOG.md +44 -2
  4. data/Gemfile.mongoid +0 -2
  5. data/Gemfile.mongoid-2.4 +2 -4
  6. data/Gemfile.mongoid-2.5 +2 -4
  7. data/Gemfile.mongoid-2.6 +1 -3
  8. data/Gemfile.mongoid-2.7 +2 -4
  9. data/Gemfile.mongoid-2.8 +2 -4
  10. data/Gemfile.mongoid-3.0 +2 -4
  11. data/Gemfile.mongoid-3.1 +2 -4
  12. data/Gemfile.mongoid-4.0 +2 -4
  13. data/Gemfile.rails-3.0 +1 -3
  14. data/Gemfile.rails-3.1 +1 -3
  15. data/Gemfile.rails-3.2 +1 -3
  16. data/Gemfile.rails-4.0 +1 -3
  17. data/Gemfile.rails-4.1 +1 -3
  18. data/Gemfile.rails-4.2 +17 -0
  19. data/README.md +55 -43
  20. data/bullet_instructure.gemspec +2 -1
  21. data/lib/bullet/active_record3.rb +68 -34
  22. data/lib/bullet/active_record3x.rb +60 -32
  23. data/lib/bullet/active_record4.rb +57 -39
  24. data/lib/bullet/active_record41.rb +83 -42
  25. data/lib/bullet/active_record42.rb +195 -0
  26. data/lib/bullet/dependency.rb +6 -0
  27. data/lib/bullet/detector/association.rb +23 -17
  28. data/lib/bullet/detector/counter_cache.rb +16 -16
  29. data/lib/bullet/detector/n_plus_one_query.rb +43 -30
  30. data/lib/bullet/detector/unused_eager_loading.rb +2 -2
  31. data/lib/bullet/ext/object.rb +6 -2
  32. data/lib/bullet/notification/base.rb +17 -18
  33. data/lib/bullet/notification/n_plus_one_query.rb +6 -4
  34. data/lib/bullet/notification/unused_eager_loading.rb +1 -1
  35. data/lib/bullet/rack.rb +21 -14
  36. data/lib/bullet/version.rb +2 -2
  37. data/lib/bullet.rb +18 -10
  38. data/spec/bullet/detector/counter_cache_spec.rb +8 -8
  39. data/spec/bullet/detector/n_plus_one_query_spec.rb +27 -27
  40. data/spec/bullet/ext/object_spec.rb +14 -0
  41. data/spec/bullet/notification/base_spec.rb +30 -18
  42. data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -3
  43. data/spec/bullet/notification/unused_eager_loading_spec.rb +1 -1
  44. data/spec/bullet/rack_spec.rb +3 -3
  45. data/spec/bullet_spec.rb +2 -2
  46. data/spec/integration/active_record3/association_spec.rb +22 -2
  47. data/spec/integration/active_record4/association_spec.rb +47 -2
  48. data/spec/models/category.rb +5 -2
  49. data/spec/models/comment.rb +2 -0
  50. data/spec/models/post.rb +8 -3
  51. data/spec/models/reply.rb +3 -0
  52. data/spec/models/submission.rb +1 -1
  53. data/spec/spec_helper.rb +4 -4
  54. data/spec/support/sqlite_seed.rb +14 -6
  55. data/test.sh +1 -0
  56. data/update.sh +14 -0
  57. metadata +26 -9
  58. data/.ruby-version +0 -1
@@ -1,3 +1,5 @@
1
+ require 'redcarpet'
2
+
1
3
  module Bullet
2
4
  module Notification
3
5
  class Base
@@ -18,25 +20,21 @@ module Bullet
18
20
  raise NoMethodError.new("no method body defined")
19
21
  end
20
22
 
23
+ def call_stack_messages
24
+ ""
25
+ end
26
+
21
27
  def whoami
22
- user = `whoami`
23
- if user
24
- "user: #{user.chomp}"
28
+ @user ||= ENV['USER'].presence || (`whoami`.chomp rescue "")
29
+ if @user.present?
30
+ "user: #{@user}"
25
31
  else
26
32
  ""
27
33
  end
28
34
  end
29
35
 
30
36
  def body_with_caller
31
- body
32
- end
33
-
34
- def standard_notice
35
- @standard_notifice ||= title + "\n" + body
36
- end
37
-
38
- def full_notice
39
- [url, title, body_with_caller].compact.join("\n")
37
+ "#{body}\n#{call_stack_messages}\n"
40
38
  end
41
39
 
42
40
  def notify_inline
@@ -48,11 +46,12 @@ module Bullet
48
46
  end
49
47
 
50
48
  def short_notice
51
- [url, title, body].compact.join("\n")
49
+ [whoami.presence, url, title, body].compact.join(" ")
52
50
  end
53
51
 
54
52
  def notification_data
55
53
  {
54
+ :user => whoami,
56
55
  :url => url,
57
56
  :title => title,
58
57
  :body => body_with_caller,
@@ -66,7 +65,7 @@ module Bullet
66
65
  def hash
67
66
  klazz_associations_str.hash
68
67
  end
69
-
68
+
70
69
  class HTMLwithPygments < Redcarpet::Render::HTML
71
70
  def block_code(code, language)
72
71
  Pygments.highlight(code, :lexer => language)
@@ -75,20 +74,20 @@ module Bullet
75
74
 
76
75
  def markdown(text)
77
76
  renderer = HTMLwithPygments.new(hard_wrap: true)
78
- options = {
77
+ options = {
79
78
  :no_intra_emphasis => true,
80
79
  :fenced_code_blocks => true
81
- }
80
+ }
82
81
  Redcarpet::Markdown.new(renderer, options).render(text).html_safe
83
82
  end
84
-
83
+
85
84
  protected
86
85
  def klazz_associations_str
87
86
  " #{@base_class} => [#{@associations.map(&:inspect).join(', ')}]"
88
87
  end
89
88
 
90
89
  def associations_str
91
- ":include => #{@associations.map{ |a| a.to_s.to_sym unless a.is_a? Hash }.inspect}"
90
+ ":includes => #{@associations.map{ |a| a.to_s.to_sym unless a.is_a? Hash }.inspect}"
92
91
  end
93
92
  end
94
93
  end
@@ -7,10 +7,6 @@ module Bullet
7
7
  @callers = callers
8
8
  end
9
9
 
10
- def body_with_caller
11
- markdown("#{body}\n#{call_stack_messages}")
12
- end
13
-
14
10
  def body
15
11
  "#{klazz_associations_str}\n Add to your finder: #{associations_str}"
16
12
  end
@@ -19,6 +15,12 @@ module Bullet
19
15
  markdown(("##")+"N+1 Query #{@path ? "in #{@path}" : 'detected'}")
20
16
  end
21
17
 
18
+ def notification_data
19
+ super.merge(
20
+ :backtrace => @callers
21
+ )
22
+ end
23
+
22
24
  protected
23
25
  def call_stack_messages
24
26
  markdown((['N+1 Query method call stack'] + @callers).join( "\n " ))
@@ -2,7 +2,7 @@ module Bullet
2
2
  module Notification
3
3
  class UnusedEagerLoading < Base
4
4
  def body
5
- markdown("#{klazz_associations_str}\n Remove from your finder: #{associations_str}\n")
5
+ "#{klazz_associations_str}\n Remove from your finder: #{associations_str}"
6
6
  end
7
7
 
8
8
  def title
data/lib/bullet/rack.rb CHANGED
@@ -10,21 +10,20 @@ 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?(response) || empty?(response)
14
13
 
15
14
  response_body = nil
16
15
  if Bullet.notification?
17
- if status == 200 && !response_body(response).frozen? && html_request?(headers, response)
18
- response_body = response_body(response) << Bullet.gather_inline_notifications
19
- add_footer_note(response_body) if Bullet.add_footer
16
+ if !file?(headers) && !sse?(headers) && !empty?(response) &&
17
+ status == 200 && !response_body(response).frozen? && html_request?(headers, response)
18
+ response_body = response_body(response)
19
+ append_to_html_body(response_body, footer_note) if Bullet.add_footer
20
+ append_to_html_body(response_body, Bullet.gather_inline_notifications)
20
21
  headers['Content-Length'] = response_body.bytesize.to_s
21
22
  end
23
+ Bullet.perform_out_of_channel_notifications(env)
22
24
  end
23
25
  [status, headers, response_body ? [response_body] : response]
24
26
  ensure
25
- if Bullet.enable? && Bullet.notification?
26
- Bullet.perform_out_of_channel_notifications(env)
27
- end
28
27
  Bullet.end_request
29
28
  end
30
29
 
@@ -42,16 +41,25 @@ module Bullet
42
41
  end
43
42
  end
44
43
 
45
- def add_footer_note(response_body)
46
- response_body << "<div #{footer_div_style}>" + Bullet.footer_info.uniq.join("<br>") + "</div>"
44
+ def append_to_html_body(response_body, content)
45
+ if response_body.include?('</body>')
46
+ position = response_body.rindex('</body>')
47
+ response_body.insert(position, content)
48
+ else
49
+ response_body << content
50
+ end
51
+ end
52
+
53
+ def footer_note
54
+ "<div #{footer_div_attributes}>" + Bullet.footer_info.uniq.join("<br>") + "</div>"
47
55
  end
48
56
 
49
57
  def file?(headers)
50
58
  headers["Content-Transfer-Encoding"] == "binary"
51
59
  end
52
60
 
53
- def sse?(response)
54
- response.respond_to?(:stream) && response.stream.is_a?(ActionController::Live::Buffer)
61
+ def sse?(headers)
62
+ headers["Content-Type"] == "text/event-stream"
55
63
  end
56
64
 
57
65
  def html_request?(headers, response)
@@ -67,9 +75,9 @@ module Bullet
67
75
  end
68
76
 
69
77
  private
70
- def footer_div_style
78
+ def footer_div_attributes
71
79
  <<EOF
72
- style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: solid; border-color: rgb(153, 153, 153);
80
+ data-is-bullet-footer ondblclick="this.parentNode.removeChild(this);" style="position: fixed; bottom: 0pt; left: 0pt; cursor: pointer; border-style: solid; border-color: rgb(153, 153, 153);
73
81
  -moz-border-top-colors: none; -moz-border-right-colors: none; -moz-border-bottom-colors: none;
74
82
  -moz-border-left-colors: none; -moz-border-image: none; border-width: 2pt 2pt 0px 0px;
75
83
  padding: 5px; border-radius: 0pt 10pt 0pt 0px; background: none repeat scroll 0% 0% rgba(200, 200, 200, 0.8);
@@ -78,4 +86,3 @@ EOF
78
86
  end
79
87
  end
80
88
  end
81
-
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Bullet
3
- VERSION = "4.0.5"
4
- end
3
+ VERSION = "4.14.7"
4
+ end
data/lib/bullet.rb CHANGED
@@ -29,7 +29,9 @@ module Bullet
29
29
  attr_reader :notification_collector, :whitelist
30
30
  attr_accessor :add_footer, :orm_pathches_applied
31
31
 
32
- delegate :alert=, :console=, :growl=, :rails_logger=, :xmpp=, :airbrake=, :bugsnag=, :to => UniformNotifier
32
+ available_notifiers = UniformNotifier::AVAILABLE_NOTIFIERS.map { |notifier| "#{notifier}=" }
33
+ available_notifiers << { :to => UniformNotifier }
34
+ delegate *available_notifiers
33
35
 
34
36
  def raise=(should_raise)
35
37
  UniformNotifier.raise=(should_raise ? Notification::UnoptimizedQueryError : false)
@@ -96,7 +98,7 @@ module Bullet
96
98
  end
97
99
 
98
100
  def debug(title, message)
99
- puts "[Bullet][#{title}] #{message}" if ENV['DEBUG'] == 'true'
101
+ puts "[Bullet][#{title}] #{message}" if ENV['BULLET_DEBUG'] == 'true'
100
102
  end
101
103
 
102
104
  def start_request
@@ -107,6 +109,7 @@ module Bullet
107
109
  Thread.current[:bullet_call_object_associations] = Bullet::Registry::Base.new
108
110
  Thread.current[:bullet_possible_objects] = Bullet::Registry::Object.new
109
111
  Thread.current[:bullet_impossible_objects] = Bullet::Registry::Object.new
112
+ Thread.current[:bullet_inversed_objects] = Bullet::Registry::Base.new
110
113
  Thread.current[:bullet_eager_loadings] = Bullet::Registry::Association.new
111
114
 
112
115
  Thread.current[:bullet_counter_possible_objects] ||= Bullet::Registry::Object.new
@@ -118,9 +121,10 @@ module Bullet
118
121
  Thread.current[:bullet_notification_collector] = nil
119
122
 
120
123
  Thread.current[:bullet_object_associations] = nil
124
+ Thread.current[:bullet_call_object_associations] = nil
121
125
  Thread.current[:bullet_possible_objects] = nil
122
126
  Thread.current[:bullet_impossible_objects] = nil
123
- Thread.current[:bullet_call_object_associations] = nil
127
+ Thread.current[:bullet_inversed_objects] = nil
124
128
  Thread.current[:bullet_eager_loadings] = nil
125
129
 
126
130
  Thread.current[:bullet_counter_possible_objects] = nil
@@ -136,6 +140,7 @@ module Bullet
136
140
  end
137
141
 
138
142
  def notification?
143
+ return unless start?
139
144
  Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
140
145
  notification_collector.notifications_present?
141
146
  end
@@ -150,14 +155,14 @@ module Bullet
150
155
 
151
156
  def perform_out_of_channel_notifications(env = {})
152
157
  for_each_active_notifier_with_notification do |notification|
153
- notification.url = [env['HTTP_HOST'], env['REQUEST_URI']].compact.join
158
+ notification.url = env['REQUEST_URI']
154
159
  notification.notify_out_of_channel
155
160
  end
156
161
  end
157
162
 
158
163
  def footer_info
159
164
  info = []
160
- for_each_active_notifier_with_notification do |notification|
165
+ notification_collector.collection.each do |notification|
161
166
  info << notification.short_notice
162
167
  end
163
168
  info
@@ -173,14 +178,17 @@ module Bullet
173
178
  end
174
179
 
175
180
  def profile
176
- Bullet.start_request if Bullet.enable?
181
+ if Bullet.enable?
182
+ begin
183
+ Bullet.start_request
177
184
 
178
- yield
185
+ yield
179
186
 
180
- if Bullet.enable? && Bullet.notification?
181
- Bullet.perform_out_of_channel_notifications
187
+ Bullet.perform_out_of_channel_notifications if Bullet.notification?
188
+ ensure
189
+ Bullet.end_request
190
+ end
182
191
  end
183
- Bullet.end_request if Bullet.enable?
184
192
  end
185
193
 
186
194
  private
@@ -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.bullet_key, [:comments]).and_return(true)
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.bullet_key, [:comments]).and_return(false)
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.send(:possible_objects)).to be_include(@post1.bullet_key)
29
- expect(CounterCache.send(:possible_objects)).to be_include(@post2.bullet_key)
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.send(:impossible_objects)).to be_include(@post1.bullet_key)
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.send(:conditions_met?, @post1.bullet_key, :associations)).to eq true
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.send(:conditions_met?, @post1.bullet_key, :associations)).to eq false
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.send(:conditions_met?, @post1.bullet_key, :associations)).to eq false
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.send(:possible?, @post.bullet_key)).to eq true
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.send(:impossible?, @post.bullet_key)).to eq true
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.send(:association?, @post.bullet_key, :association)).to eq true
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.send(:association?, @post.bullet_key, :associatio2)).to eq false
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.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
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.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
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.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
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.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
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.bullet_key, :association).and_return(true)
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.bullet_key, :association).and_return(false)
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.bullet_key, :association).and_return(true)
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.bullet_key, :association).and_return(true)
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.send(:possible_objects)).to be_include(@post.bullet_key)
122
- expect(NPlusOneQuery.send(:possible_objects)).to be_include(@post2.bullet_key)
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.send(:impossible_objects)).to be_include(@post.bullet_key)
133
+ expect(NPlusOneQuery.impossible_objects).to be_include(@post.bullet_key)
134
134
  end
135
135
  end
136
136
  end
@@ -14,4 +14,18 @@ describe Object do
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
@@ -22,30 +22,42 @@ module Bullet
22
22
  user = `whoami`.chomp
23
23
  expect(subject.whoami).to eq("user: #{user}")
24
24
  end
25
- end
26
25
 
27
- context "#body_with_caller" do
28
- it "should return body" do
29
- allow(subject).to receive(:body).and_return("body")
30
- expect(subject.body_with_caller).to eq("body")
26
+ it "should leverage ENV parameter" do
27
+ temp_env_variable("USER", "bogus") do
28
+ expect(subject.whoami).to eq("user: bogus")
29
+ end
31
30
  end
32
- end
33
31
 
34
- context "#standard_notice" do
35
- it "should return title + body" do
36
- allow(subject).to receive(:title).and_return("title")
37
- allow(subject).to receive(:body).and_return("body")
38
- expect(subject.standard_notice).to eq("title\nbody")
32
+ it "should return blank if no user available" do
33
+ temp_env_variable("USER","") do
34
+ expect(subject).to receive(:`).with("whoami").and_return("")
35
+ expect(subject.whoami).to eq("")
36
+ end
39
37
  end
38
+
39
+ it "should return blank if whoami is not available" do
40
+ temp_env_variable("USER","") do
41
+ expect(subject).to receive(:`).with("whoami").and_raise(Errno::ENOENT)
42
+ expect(subject.whoami).to eq("")
43
+ end
44
+ end
45
+
46
+ def temp_env_variable(name, value)
47
+ old_value = ENV[name]
48
+ ENV[name] = value
49
+ yield
50
+ ensure
51
+ ENV[name] = old_value
52
+ end
53
+
40
54
  end
41
55
 
42
- context "#full_notice" do
43
- it "should return whoami + url + title + body_with_caller" do
44
- allow(subject).to receive(:whoami).and_return("whoami")
45
- allow(subject).to receive(:url).and_return("url")
46
- allow(subject).to receive(:title).and_return("title")
47
- allow(subject).to receive(:body_with_caller).and_return("body_with_caller")
48
- expect(subject.full_notice).to eq("whoami\nurl\ntitle\nbody_with_caller")
56
+ context "#body_with_caller" do
57
+ it "should return body" do
58
+ allow(subject).to receive(:body).and_return("body")
59
+ allow(subject).to receive(:call_stack_messages).and_return("call_stack_messages")
60
+ expect(subject.body_with_caller).to eq("body\ncall_stack_messages\n")
49
61
  end
50
62
  end
51
63
 
@@ -5,9 +5,9 @@ module Bullet
5
5
  describe NPlusOneQuery do
6
6
  subject { NPlusOneQuery.new([["caller1", "caller2"]], Post, [:comments, :votes], "path") }
7
7
 
8
- it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2") }
9
- it { expect([ subject.body_with_caller, subject.body_with_caller]).to eq([ " Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2", " Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2" ]) }
10
- it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :include => [:comments, :votes]") }
8
+ it { expect(subject.body_with_caller).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2\n") }
9
+ it { expect([subject.body_with_caller, subject.body_with_caller]).to eq([ " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2\n", " Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]\nN+1 Query method call stack\n caller1\n caller2\n" ]) }
10
+ it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your finder: :includes => [:comments, :votes]") }
11
11
  it { expect(subject.title).to eq("N+1 Query in path") }
12
12
  end
13
13
  end
@@ -5,7 +5,7 @@ module Bullet
5
5
  describe UnusedEagerLoading do
6
6
  subject { UnusedEagerLoading.new(Post, [:comments, :votes], "path") }
7
7
 
8
- it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :include => [:comments, :votes]") }
8
+ it { expect(subject.body).to eq(" Post => [:comments, :votes]\n Remove from your finder: :includes => [:comments, :votes]") }
9
9
  it { expect(subject.title).to eq("Unused Eager Loading in path") }
10
10
  end
11
11
  end
@@ -65,19 +65,19 @@ module Bullet
65
65
  end
66
66
 
67
67
  it "should change response body if notification is active" do
68
- expect(Bullet).to receive(:notification?).and_return(true).twice
68
+ expect(Bullet).to receive(:notification?).and_return(true)
69
69
  expect(Bullet).to receive(:gather_inline_notifications).and_return("<bullet></bullet>")
70
70
  expect(Bullet).to receive(:perform_out_of_channel_notifications)
71
71
  status, headers, response = middleware.call([200, {"Content-Type" => "text/html"}])
72
72
  expect(headers["Content-Length"]).to eq("56")
73
- expect(response).to eq(["<html><head></head><body></body></html><bullet></bullet>"])
73
+ expect(response).to eq(["<html><head></head><body><bullet></bullet></body></html>"])
74
74
  end
75
75
 
76
76
  it "should set the right Content-Length if response body contains accents" do
77
77
  response = Support::ResponseDouble.new
78
78
  response.body = "<html><head></head><body>é</body></html>"
79
79
  app.response = response
80
- expect(Bullet).to receive(:notification?).and_return(true).twice
80
+ expect(Bullet).to receive(:notification?).and_return(true)
81
81
  expect(Bullet).to receive(:gather_inline_notifications).and_return("<bullet></bullet>")
82
82
  status, headers, response = middleware.call([200, {"Content-Type" => "text/html"}])
83
83
  expect(headers["Content-Length"]).to eq("58")
data/spec/bullet_spec.rb CHANGED
@@ -26,8 +26,8 @@ describe Bullet, focused: true do
26
26
 
27
27
  context 'enable Bullet again without patching again the orms' do
28
28
  before do
29
- Bullet::Mongoid.should_not_receive(:enable) if defined? Bullet::Mongoid
30
- Bullet::ActiveRecord.should_not_receive(:enable) if defined? Bullet::ActiveRecord
29
+ expect(Bullet::Mongoid).not_to receive(:enable) if defined? Bullet::Mongoid
30
+ expect(Bullet::ActiveRecord).not_to receive(:enable) if defined? Bullet::ActiveRecord
31
31
  Bullet.enable = true
32
32
  end
33
33