bullet 4.6.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +10 -4
  6. data/Gemfile +4 -5
  7. data/Gemfile.lock +160 -0
  8. data/Gemfile.mongoid +15 -0
  9. data/Gemfile.mongoid-2.4.12 +15 -0
  10. data/Gemfile.mongoid-2.4.12.lock +163 -0
  11. data/Gemfile.mongoid-2.5.2 +15 -0
  12. data/Gemfile.mongoid-2.5.2.lock +163 -0
  13. data/Gemfile.mongoid-2.6.0 +15 -0
  14. data/Gemfile.mongoid-2.6.0.lock +163 -0
  15. data/Gemfile.mongoid-2.7.1 +15 -0
  16. data/Gemfile.mongoid-2.7.1.lock +163 -0
  17. data/Gemfile.mongoid-2.8.1 +15 -0
  18. data/Gemfile.mongoid-2.8.1.lock +166 -0
  19. data/Gemfile.mongoid-3.0.23 +15 -0
  20. data/Gemfile.mongoid-3.0.23.lock +163 -0
  21. data/Gemfile.mongoid-3.1.5 +15 -0
  22. data/Gemfile.mongoid-3.1.5.lock +163 -0
  23. data/Gemfile.mongoid.lock +167 -0
  24. data/Gemfile.rails-3.0.20 +3 -4
  25. data/Gemfile.rails-3.0.20.lock +147 -0
  26. data/Gemfile.rails-3.1.12 +14 -0
  27. data/Gemfile.rails-3.1.12.lock +157 -0
  28. data/Gemfile.rails-3.2.15 +14 -0
  29. data/Gemfile.rails-3.2.15.lock +155 -0
  30. data/Gemfile.rails-4.0.1 +14 -0
  31. data/Gemfile.rails-4.0.1.lock +150 -0
  32. data/README.md +16 -16
  33. data/bullet.gemspec +2 -1
  34. data/lib/bullet.rb +26 -2
  35. data/lib/bullet/dependency.rb +14 -23
  36. data/lib/bullet/mongoid4x.rb +55 -0
  37. data/lib/bullet/notification.rb +2 -0
  38. data/lib/bullet/notification/base.rb +4 -0
  39. data/lib/bullet/rack.rb +24 -3
  40. data/lib/bullet/version.rb +1 -1
  41. data/spec/bullet/detector/unused_eager_loading_spec.rb +1 -1
  42. data/spec/bullet/notification/base_spec.rb +2 -2
  43. data/spec/bullet/rack_spec.rb +9 -9
  44. data/spec/integration/{association_spec.rb → active_record3/association_spec.rb} +1 -1
  45. data/spec/integration/active_record4/association_spec.rb +698 -0
  46. data/spec/integration/mongoid/association_spec.rb +10 -7
  47. data/spec/models/client.rb +1 -1
  48. data/spec/models/comment.rb +2 -2
  49. data/spec/models/document.rb +2 -2
  50. data/spec/models/firm.rb +1 -1
  51. data/spec/models/mongoid/address.rb +2 -0
  52. data/spec/models/mongoid/category.rb +2 -0
  53. data/spec/models/mongoid/comment.rb +2 -0
  54. data/spec/models/mongoid/company.rb +2 -0
  55. data/spec/models/mongoid/entry.rb +2 -0
  56. data/spec/models/mongoid/post.rb +2 -0
  57. data/spec/models/mongoid/user.rb +2 -0
  58. data/spec/models/newspaper.rb +1 -1
  59. data/spec/models/pet.rb +1 -1
  60. data/spec/models/post.rb +3 -5
  61. data/spec/spec_helper.rb +21 -0
  62. data/spec/support/mongo_seed.rb +13 -1
  63. data/test.sh +12 -4
  64. metadata +49 -11
  65. data/.rvmrc +0 -2
  66. data/.rvmrc.example +0 -2
  67. data/Gemfile.rails-3.1.11 +0 -16
  68. data/Gemfile.rails-3.2.12 +0 -16
  69. data/Gemfile.rails-4-beta +0 -14
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'rails', '4.0.1'
6
+ gem 'sqlite3'
7
+ gem 'mysql2'
8
+ gem 'activerecord-import'
9
+
10
+ gem "rspec"
11
+ gem "guard"
12
+ gem "guard-rspec"
13
+
14
+ gem 'coveralls', require: false
@@ -0,0 +1,150 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bullet (4.7.0)
5
+ activesupport
6
+ uniform_notifier (>= 1.3.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionmailer (4.0.1)
12
+ actionpack (= 4.0.1)
13
+ mail (~> 2.5.4)
14
+ actionpack (4.0.1)
15
+ activesupport (= 4.0.1)
16
+ builder (~> 3.1.0)
17
+ erubis (~> 2.7.0)
18
+ rack (~> 1.5.2)
19
+ rack-test (~> 0.6.2)
20
+ activemodel (4.0.1)
21
+ activesupport (= 4.0.1)
22
+ builder (~> 3.1.0)
23
+ activerecord (4.0.1)
24
+ activemodel (= 4.0.1)
25
+ activerecord-deprecated_finders (~> 1.0.2)
26
+ activesupport (= 4.0.1)
27
+ arel (~> 4.0.0)
28
+ activerecord-deprecated_finders (1.0.3)
29
+ activerecord-import (0.4.1)
30
+ activerecord (>= 3.0)
31
+ activesupport (4.0.1)
32
+ i18n (~> 0.6, >= 0.6.4)
33
+ minitest (~> 4.2)
34
+ multi_json (~> 1.3)
35
+ thread_safe (~> 0.1)
36
+ tzinfo (~> 0.3.37)
37
+ arel (4.0.1)
38
+ atomic (1.1.14)
39
+ builder (3.1.4)
40
+ coderay (1.0.9)
41
+ colorize (0.5.8)
42
+ coveralls (0.6.7)
43
+ colorize
44
+ multi_json (~> 1.3)
45
+ rest-client
46
+ simplecov (>= 0.7)
47
+ thor
48
+ diff-lcs (1.2.4)
49
+ erubis (2.7.0)
50
+ ffi (1.9.0)
51
+ formatador (0.2.4)
52
+ guard (1.8.2)
53
+ formatador (>= 0.2.4)
54
+ listen (>= 1.0.0)
55
+ lumberjack (>= 1.0.2)
56
+ pry (>= 0.9.10)
57
+ thor (>= 0.14.6)
58
+ guard-rspec (3.0.2)
59
+ guard (>= 1.8)
60
+ rspec (~> 2.13)
61
+ hike (1.2.3)
62
+ i18n (0.6.5)
63
+ listen (1.3.0)
64
+ rb-fsevent (>= 0.9.3)
65
+ rb-inotify (>= 0.9)
66
+ rb-kqueue (>= 0.2)
67
+ lumberjack (1.0.4)
68
+ mail (2.5.4)
69
+ mime-types (~> 1.16)
70
+ treetop (~> 1.4.8)
71
+ method_source (0.8.2)
72
+ mime-types (1.25)
73
+ minitest (4.7.5)
74
+ multi_json (1.8.2)
75
+ mysql2 (0.3.13)
76
+ polyglot (0.3.3)
77
+ pry (0.9.12.2)
78
+ coderay (~> 1.0.5)
79
+ method_source (~> 0.8)
80
+ slop (~> 3.4)
81
+ rack (1.5.2)
82
+ rack-test (0.6.2)
83
+ rack (>= 1.0)
84
+ rails (4.0.1)
85
+ actionmailer (= 4.0.1)
86
+ actionpack (= 4.0.1)
87
+ activerecord (= 4.0.1)
88
+ activesupport (= 4.0.1)
89
+ bundler (>= 1.3.0, < 2.0)
90
+ railties (= 4.0.1)
91
+ sprockets-rails (~> 2.0.0)
92
+ railties (4.0.1)
93
+ actionpack (= 4.0.1)
94
+ activesupport (= 4.0.1)
95
+ rake (>= 0.8.7)
96
+ thor (>= 0.18.1, < 2.0)
97
+ rake (10.1.0)
98
+ rb-fsevent (0.9.3)
99
+ rb-inotify (0.9.1)
100
+ ffi (>= 0.5.0)
101
+ rb-kqueue (0.2.0)
102
+ ffi (>= 0.5.0)
103
+ rest-client (1.6.7)
104
+ mime-types (>= 1.16)
105
+ rspec (2.14.1)
106
+ rspec-core (~> 2.14.0)
107
+ rspec-expectations (~> 2.14.0)
108
+ rspec-mocks (~> 2.14.0)
109
+ rspec-core (2.14.5)
110
+ rspec-expectations (2.14.2)
111
+ diff-lcs (>= 1.1.3, < 2.0)
112
+ rspec-mocks (2.14.3)
113
+ simplecov (0.7.1)
114
+ multi_json (~> 1.0)
115
+ simplecov-html (~> 0.7.1)
116
+ simplecov-html (0.7.1)
117
+ slop (3.4.6)
118
+ sprockets (2.10.0)
119
+ hike (~> 1.2)
120
+ multi_json (~> 1.0)
121
+ rack (~> 1.0)
122
+ tilt (~> 1.1, != 1.3.0)
123
+ sprockets-rails (2.0.1)
124
+ actionpack (>= 3.0)
125
+ activesupport (>= 3.0)
126
+ sprockets (~> 2.8)
127
+ sqlite3 (1.3.8)
128
+ thor (0.18.1)
129
+ thread_safe (0.1.3)
130
+ atomic
131
+ tilt (1.4.1)
132
+ treetop (1.4.15)
133
+ polyglot
134
+ polyglot (>= 0.3.1)
135
+ tzinfo (0.3.38)
136
+ uniform_notifier (1.3.0)
137
+
138
+ PLATFORMS
139
+ ruby
140
+
141
+ DEPENDENCIES
142
+ activerecord-import
143
+ bullet!
144
+ coveralls
145
+ guard
146
+ guard-rspec
147
+ mysql2
148
+ rails (= 4.0.1)
149
+ rspec
150
+ sqlite3
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Bullet
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/bullet.png)](http://badge.fury.io/rb/bullet)
3
4
  [![Build Status](https://secure.travis-ci.org/flyerhzm/bullet.png)](http://travis-ci.org/flyerhzm/bullet)
5
+ [![Coverage Status](https://coveralls.io/repos/flyerhzm/bullet/badge.png?branch=master)](https://coveralls.io/r/flyerhzm/bullet)
4
6
 
5
7
  [![Coderwall Endorse](http://api.coderwall.com/flyerhzm/endorsecount.png)](http://coderwall.com/flyerhzm)
6
8
 
@@ -43,7 +45,7 @@ Bullet won't do ANYTHING unless you tell it to explicitly. Append to
43
45
  ```ruby
44
46
  config.after_initialize do
45
47
  Bullet.enable = true
46
- Bullet.alert = true
48
+ Bullet.alert = true
47
49
  Bullet.bullet_logger = true
48
50
  Bullet.console = true
49
51
  Bullet.growl = true
@@ -53,6 +55,7 @@ config.after_initialize do
53
55
  :show_online_status => true }
54
56
  Bullet.rails_logger = true
55
57
  Bullet.airbrake = true
58
+ Bullet.add_footer = true
56
59
  end
57
60
  ```
58
61
 
@@ -67,6 +70,8 @@ The code above will enable all seven of the Bullet notification systems:
67
70
  * `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
68
71
  * `Bullet.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
69
72
  * `Bullet.xmpp`: send XMPP/Jabber notifications to the receiver indicated. Note that the code will currently not handle the adding of contacts, so you will need to make both accounts indicated know each other manually before you will receive any notifications. If you restart the development server frequently, the 'coming online' sound for the bullet account may start to annoy - in this case set :show_online_status to false; you will still get notifications, but the bullet account won't announce it's online status anymore.
73
+ * `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
74
+ * `Bullet.add_footer`: adds the details in the bottom left corner of the page
70
75
 
71
76
  Bullet also allows you to disable n_plus_one_query, unused_eager_loading
72
77
  and counter_cache detectors respectively
@@ -131,20 +136,17 @@ see [https://github.com/flyerhzm/uniform_notifier](https://github.com/flyerhzm/u
131
136
 
132
137
  If you find bullet does not work for you, *please disable your browser's cache*.
133
138
 
134
- ## Advance
139
+ ## Advanced
135
140
 
136
- The bullet gem use rack middleware for http request. If you want to bullet for without http server, such as job server. You can do like this:
141
+ The bullet gem uses rack middleware to profile requests. If you want to use bullet without an http server, like to profile a job, you can do this:
137
142
 
138
143
  ```ruby
139
- Bullet.start_request if Bullet.enable?
140
- # run job
141
- if Bullet.enable? && Bullet.notification?
142
- Bullet.perform_out_of_channel_notifications
144
+ Bullet.profile do
145
+ # run job
143
146
  end
144
- Bullet.end_request if Bullet.enable?
145
147
  ```
146
148
 
147
- Or you want to use it in test mode
149
+ Or to use it in test mode:
148
150
 
149
151
  ```ruby
150
152
  before(:each)
@@ -159,19 +161,16 @@ after(:each)
159
161
  end
160
162
  ```
161
163
 
162
- Don't forget enabling bullet in test environment.
164
+ Don't forget to enable bullet in your test environment.
163
165
 
164
166
  ### API access
165
167
 
166
- after `end_request`, you can fetch warnings then do whatever you want
168
+ after `profile`, you can fetch warnings then do whatever you want
167
169
 
168
170
  ```ruby
169
- Bullet.start_request if Bullet.enable?
170
- # run anything
171
- if Bullet.enable? && Bullet.notification?
172
- Bullet.perform_out_of_channel_notifications
171
+ Bullet.profile do
172
+ # run anything
173
173
  end
174
- Bullet.end_request if Bullet.enable?
175
174
  warnings = Bullet.warnings
176
175
  ```
177
176
 
@@ -253,6 +252,7 @@ config.after_initialize do
253
252
  Bullet.console = true
254
253
  # Bullet.growl = true
255
254
  Bullet.rails_logger = true
255
+ Bullet.add_footer = true
256
256
  end
257
257
  ```
258
258
 
@@ -15,7 +15,8 @@ Gem::Specification.new do |s|
15
15
 
16
16
  s.required_rubygems_version = ">= 1.3.6"
17
17
 
18
- s.add_dependency "uniform_notifier"
18
+ s.add_dependency "activesupport"
19
+ s.add_dependency "uniform_notifier", ">= 1.3.0"
19
20
 
20
21
  s.files = `git ls-files`.split("\n")
21
22
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,3 +1,4 @@
1
+ require "active_support/core_ext/module/delegation"
1
2
  require 'set'
2
3
  require 'uniform_notifier'
3
4
  require 'bullet/ext/object'
@@ -10,7 +11,6 @@ module Bullet
10
11
  autoload :ActiveRecord, "bullet/#{active_record_version}" if active_record?
11
12
  autoload :Mongoid, "bullet/#{mongoid_version}" if mongoid?
12
13
  autoload :Rack, 'bullet/rack'
13
- autoload :BulletLogger, 'bullet/logger'
14
14
  autoload :Notification, 'bullet/notification'
15
15
  autoload :Detector, 'bullet/detector'
16
16
  autoload :Registry, 'bullet/registry'
@@ -24,12 +24,17 @@ module Bullet
24
24
  end
25
25
  end
26
26
 
27
- class <<self
27
+ class << self
28
28
  attr_writer :enable, :n_plus_one_query_enable, :unused_eager_loading_enable, :counter_cache_enable
29
29
  attr_reader :notification_collector, :whitelist
30
+ attr_accessor :add_footer
30
31
 
31
32
  delegate :alert=, :console=, :growl=, :rails_logger=, :xmpp=, :airbrake=, :to => UniformNotifier
32
33
 
34
+ def raise=(should_raise)
35
+ UniformNotifier.raise=(should_raise ? Notification::UnoptimizedQueryError : false)
36
+ end
37
+
33
38
  DETECTORS = [ Bullet::Detector::NPlusOneQuery,
34
39
  Bullet::Detector::UnusedEagerLoading,
35
40
  Bullet::Detector::CounterCache ]
@@ -117,6 +122,14 @@ module Bullet
117
122
  end
118
123
  end
119
124
 
125
+ def footer_info
126
+ info = []
127
+ for_each_active_notifier_with_notification do |notification|
128
+ info << notification.short_notice
129
+ end
130
+ info
131
+ end
132
+
120
133
  def warnings
121
134
  notification_collector.collection.inject({}) do |warnings, notification|
122
135
  warning_type = notification.class.to_s.split(':').last.tableize
@@ -126,6 +139,17 @@ module Bullet
126
139
  end
127
140
  end
128
141
 
142
+ def profile
143
+ Bullet.start_request if Bullet.enable?
144
+
145
+ yield
146
+
147
+ if Bullet.enable? && Bullet.notification?
148
+ Bullet.perform_out_of_channel_notifications
149
+ end
150
+ Bullet.end_request if Bullet.enable?
151
+ end
152
+
129
153
  private
130
154
  def for_each_active_notifier_with_notification
131
155
  UniformNotifier.active_notifiers.each do |notifier|
@@ -1,21 +1,15 @@
1
1
  module Bullet
2
2
  module Dependency
3
3
  def mongoid?
4
- @mongoid ||= begin
5
- require 'mongoid'
6
- mongoid_version.present?
7
- rescue LoadError
8
- false
9
- end
4
+ @mongoid ||= defined? ::Mongoid
10
5
  end
11
6
 
12
7
  def active_record?
13
- @active_record ||= begin
14
- require 'active_record'
15
- true
16
- rescue LoadError
17
- false
18
- end
8
+ @active_record ||= defined? ::ActiveRecord
9
+ end
10
+
11
+ def rails?
12
+ @rails ||= defined? ::Rails
19
13
  end
20
14
 
21
15
  def active_record_version
@@ -36,16 +30,18 @@ module Bullet
36
30
  'mongoid2x'
37
31
  elsif mongoid3x?
38
32
  'mongoid3x'
33
+ elsif mongoid4x?
34
+ 'mongoid4x'
39
35
  end
40
36
  end
41
37
  end
42
38
 
43
39
  def active_record3?
44
- ::ActiveRecord::VERSION::MAJOR == 3
40
+ active_record? && ::ActiveRecord::VERSION::MAJOR == 3
45
41
  end
46
42
 
47
43
  def active_record4?
48
- ::ActiveRecord::VERSION::MAJOR == 4
44
+ active_record? && ::ActiveRecord::VERSION::MAJOR == 4
49
45
  end
50
46
 
51
47
  def active_record30?
@@ -61,20 +57,15 @@ module Bullet
61
57
  end
62
58
 
63
59
  def mongoid2x?
64
- ::Mongoid::VERSION =~ /\A2\.[4|5]/
60
+ mongoid? && ::Mongoid::VERSION =~ /\A2\.[4-8]/
65
61
  end
66
62
 
67
63
  def mongoid3x?
68
- ::Mongoid::VERSION =~ /\A3/
64
+ mongoid? && ::Mongoid::VERSION =~ /\A3/
69
65
  end
70
66
 
71
- def rails?
72
- @rails ||= begin
73
- require 'rails'
74
- true
75
- rescue LoadError
76
- false
77
- end
67
+ def mongoid4x?
68
+ mongoid? && ::Mongoid::VERSION =~ /\A4/
78
69
  end
79
70
  end
80
71
  end
@@ -0,0 +1,55 @@
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 = query.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_set_relation, :set_relation
45
+
46
+ def set_relation(name, relation)
47
+ if relation && relation.metadata.macro !~ /embed/
48
+ Bullet::Detector::NPlusOneQuery.call_association(self, name)
49
+ end
50
+ origin_set_relation(name, relation)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end