bullet 4.13.1 → 5.5.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -11
  4. data/CHANGELOG.md +62 -3
  5. data/Gemfile.mongoid +0 -2
  6. data/Gemfile.mongoid-4.0 +1 -5
  7. data/{Gemfile.mongoid-2.8 → Gemfile.mongoid-5.0} +2 -6
  8. data/{Gemfile.mongoid-2.5 → Gemfile.mongoid-6.0} +2 -6
  9. data/Gemfile.rails-4.0 +2 -5
  10. data/Gemfile.rails-4.1 +2 -5
  11. data/{Gemfile.rails-3.0 → Gemfile.rails-4.2} +3 -6
  12. data/{Gemfile.rails-3.1 → Gemfile.rails-5.0} +2 -6
  13. data/Hacking.md +1 -0
  14. data/README.md +39 -7
  15. data/bullet.gemspec +1 -1
  16. data/lib/bullet/active_record4.rb +109 -33
  17. data/lib/bullet/active_record41.rb +99 -37
  18. data/lib/bullet/active_record42.rb +251 -0
  19. data/lib/bullet/active_record5.rb +243 -0
  20. data/lib/bullet/dependency.rb +34 -28
  21. data/lib/bullet/detector/association.rb +16 -16
  22. data/lib/bullet/detector/counter_cache.rb +13 -13
  23. data/lib/bullet/detector/n_plus_one_query.rb +30 -35
  24. data/lib/bullet/detector/unused_eager_loading.rb +12 -11
  25. data/lib/bullet/ext/object.rb +4 -2
  26. data/lib/bullet/{mongoid3x.rb → mongoid5x.rb} +3 -3
  27. data/lib/bullet/{mongoid2x.rb → mongoid6x.rb} +12 -12
  28. data/lib/bullet/notification/base.rb +9 -13
  29. data/lib/bullet/notification/n_plus_one_query.rb +8 -6
  30. data/lib/bullet/notification/unused_eager_loading.rb +18 -1
  31. data/lib/bullet/rack.rb +28 -16
  32. data/lib/bullet/stack_trace_filter.rb +34 -0
  33. data/lib/bullet/version.rb +1 -1
  34. data/lib/bullet.rb +48 -14
  35. data/spec/bullet/detector/counter_cache_spec.rb +8 -8
  36. data/spec/bullet/detector/n_plus_one_query_spec.rb +46 -31
  37. data/spec/bullet/detector/unused_eager_loading_spec.rb +17 -3
  38. data/spec/bullet/ext/object_spec.rb +6 -0
  39. data/spec/bullet/notification/base_spec.rb +4 -29
  40. data/spec/bullet/notification/n_plus_one_query_spec.rb +4 -4
  41. data/spec/bullet/notification/unused_eager_loading_spec.rb +3 -3
  42. data/spec/bullet/rack_spec.rb +38 -7
  43. data/spec/bullet_spec.rb +93 -0
  44. data/spec/integration/active_record4/association_spec.rb +112 -4
  45. data/spec/integration/{active_record3 → active_record5}/association_spec.rb +121 -15
  46. data/spec/integration/counter_cache_spec.rb +24 -1
  47. data/spec/models/category.rb +4 -1
  48. data/spec/models/comment.rb +2 -0
  49. data/spec/models/post.rb +7 -2
  50. data/spec/models/reply.rb +3 -0
  51. data/spec/models/submission.rb +1 -1
  52. data/spec/spec_helper.rb +3 -5
  53. data/spec/support/mongo_seed.rb +13 -0
  54. data/spec/support/sqlite_seed.rb +15 -6
  55. data/test.sh +4 -10
  56. data/update.sh +7 -0
  57. metadata +21 -23
  58. data/Gemfile.mongoid-2.4 +0 -19
  59. data/Gemfile.mongoid-2.6 +0 -19
  60. data/Gemfile.mongoid-2.7 +0 -19
  61. data/Gemfile.mongoid-3.0 +0 -19
  62. data/Gemfile.mongoid-3.1 +0 -19
  63. data/Gemfile.rails-3.2 +0 -19
  64. data/lib/bullet/active_record3.rb +0 -154
  65. data/lib/bullet/active_record3x.rb +0 -134
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c4c663f19d349dc9be3a82803ba5e5af344ed0e2
4
- data.tar.gz: f996a53cd2ce05eb85f11e55477b41d7b6f841f8
3
+ metadata.gz: 7f8cac0418ea4a1bb9f8abc6c12e84022f2f118d
4
+ data.tar.gz: ebdf99115037dec22a5480a63d3bed5f15956dda
5
5
  SHA512:
6
- metadata.gz: 9fe6ad4a5e0b23c19815a121e8b3dec2989c04f2e81836eba4a096a06b68ae7b33c7c202c1a7a99e697a48bd5bd29711b7ad0a2b17e1d203e32cc964a0e95314
7
- data.tar.gz: 77e4bc950eaa4e0e87fd32beaa6f11a605e1e443b0de0f3fbea89798cd11721c3c6a4fa0c9f70bad5c3b7f65586a56b050e38265a21d57d57244e219ab0f8501
6
+ metadata.gz: 0904f996964a403a495af310bab8a0612e614eb72a71d08646948508c25d4bf36d2b939da65156a5fc81595477820e0f123aa2a88d618fe97e28e81a6b6f8ada
7
+ data.tar.gz: d491e12ccce38a26a5e3d27d3f6b84acafe34bb7b6aff56b78a8e22a73a5a3abf88443110587de0080e50b32ef70d8ca387eab5faac0b1bec16efed04bf3acc1
data/.gitignore CHANGED
@@ -12,3 +12,4 @@ benchmark_profile*
12
12
  coverage/
13
13
  .coveralls.yml
14
14
  Gemfile*.lock
15
+ .idea/
data/.travis.yml CHANGED
@@ -1,19 +1,15 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
- - 2.1.2
4
+ - 2.3.0
4
5
  gemfile:
6
+ - Gemfile.rails-5.0
7
+ - Gemfile.rails-4.2
5
8
  - Gemfile.rails-4.1
6
9
  - Gemfile.rails-4.0
7
- - Gemfile.rails-3.2
8
- - Gemfile.rails-3.1
9
- - Gemfile.rails-3.0
10
- - Gemfile.mongoid-3.1
11
- - Gemfile.mongoid-3.0
12
- - Gemfile.mongoid-2.8
13
- - Gemfile.mongoid-2.7
14
- - Gemfile.mongoid-2.6
15
- - Gemfile.mongoid-2.5
16
- - Gemfile.mongoid-2.4
10
+ - Gemfile.mongoid-6.0
11
+ - Gemfile.mongoid-5.0
12
+ - Gemfile.mongoid-4.0
17
13
  env:
18
14
  - DB=sqlite
19
15
  services:
data/CHANGELOG.md CHANGED
@@ -1,8 +1,67 @@
1
1
  # Next Release
2
2
 
3
- ## 4.13.1
4
-
5
- * Fix swallow exception issue
3
+ ## 5.5.0 (12/30/2016)
4
+
5
+ * Display http request method #311
6
+ * Add close button to footer
7
+ * Raise an error if bullet does not support AR or Mongoid
8
+ * Avoid double backtrace
9
+ * Fix false alert on counter cache when associations are already loaded #288
10
+ * Fix "false alert" in rails 5 #239
11
+ * Do not support ActiveRecord 3.x and Mongoid 3.x / 4.x anymore
12
+
13
+ ## 5.4.0 (10/09/2016)
14
+
15
+ * Support rails 5.1
16
+ * Extract stack trace filtering into module
17
+
18
+ ## 5.3.0 (15/08/2016)
19
+
20
+ * Fix false alert on through association with join sql #301
21
+ * Fix association.target in `through_association` can be singular #302
22
+ * Support `find_by_sql` #303
23
+ * Fix env `REQUEST_URI`
24
+
25
+ ## 5.2.0 (07/26/2016)
26
+
27
+ * Fix `has_cached_counter?` is not defined in HABTM #297
28
+ * Fix false alert if preloaded association has no records #260
29
+ * Support Rails 5.0.0
30
+
31
+ ## 5.1.0 (05/21/2016)
32
+
33
+ * Fix false alert when `empty?` used with `counter_cache`
34
+ * Fix `alias_method_chain` deprecation for rails 5
35
+ * Add response handling for non-Rails Rack responses
36
+ * Fix false alert when querying immediately after creation
37
+ * Fix UnusedEagerLoading bug when multiple eager loading query include same objects
38
+
39
+ ## 5.0.0 (01/06/2016)
40
+
41
+ * Support Rails 5.0.0.beta1
42
+ * Fix `has_many :through` infinite loop issue
43
+ * Support mongoid 5.0.0
44
+ * Do not report association queries immediately after object creation to
45
+ require a preload
46
+ * Detect `counter_cache` for `has_many :through` association
47
+ * Compatible with `composite_primary_keys` gem
48
+ * Fix AR 4.2 SingularAssociation#reader result can be nil
49
+ * `perform_out_of_channel_notifications` should always be triggered
50
+ * Fix false positive with `belongs_to` -> `belongs_to` for active\_record 4.2
51
+ * Activate active\_record hacks only when Bullet already start
52
+ * Don't execute query when running `to_sql`
53
+ * Send backtrace to `uniform_notifier`
54
+ * Fix sse response check
55
+ * Dynamically delegate available notifiers to UniformNotifier
56
+ * Hotfix nil object when `add_impossible_object`
57
+ * Fix `has_one` then `has_many` associations in rails 4.2
58
+ * Append js and dom to html body in proper position
59
+
60
+ ## 4.14.0 (10/03/2014)
61
+
62
+ * Support rails 4.2
63
+ * Polish notification output
64
+ * Fix warning: `*' interpreted as argument prefix
6
65
 
7
66
  ## 4.13.0 (07/19/2014)
8
67
 
data/Gemfile.mongoid CHANGED
@@ -8,7 +8,5 @@ gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'mongoid', github: 'mongoid/mongoid'
9
9
 
10
10
  gem "rspec"
11
- gem "guard"
12
- gem "guard-rspec"
13
11
 
14
12
  gem 'coveralls', require: false
data/Gemfile.mongoid-4.0 CHANGED
@@ -2,16 +2,12 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 4.0.5'
5
+ gem 'rails', '~> 4.0.0'
6
6
  gem 'sqlite3', platforms: [:ruby]
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'mongoid', '~> 4.0.0'
9
9
 
10
10
  gem "rspec"
11
- gem "guard"
12
- gem "guard-rspec"
13
-
14
- gem 'coveralls', require: false
15
11
 
16
12
  platforms :rbx do
17
13
  gem 'rubysl', '~> 2.0'
@@ -2,16 +2,12 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 3.2'
5
+ gem 'rails', '~> 4.0.0'
6
6
  gem 'sqlite3', platforms: [:ruby]
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
- gem 'mongoid', '~> 2.8'
8
+ gem 'mongoid', '~> 5.1.0'
9
9
 
10
10
  gem "rspec"
11
- gem "guard"
12
- gem "guard-rspec"
13
-
14
- gem 'coveralls', require: false
15
11
 
16
12
  platforms :rbx do
17
13
  gem 'rubysl', '~> 2.0'
@@ -2,16 +2,12 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 3.2.16'
5
+ gem 'rails', '~> 5.0.0'
6
6
  gem 'sqlite3', platforms: [:ruby]
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
- gem 'mongoid', '~> 2.5.2'
8
+ gem 'mongoid', '~> 6.0.0'
9
9
 
10
10
  gem "rspec"
11
- gem "guard"
12
- gem "guard-rspec"
13
-
14
- gem 'coveralls', require: false
15
11
 
16
12
  platforms :rbx do
17
13
  gem 'rubysl', '~> 2.0'
data/Gemfile.rails-4.0 CHANGED
@@ -2,16 +2,13 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 4.0.8'
5
+ gem 'rails', '~> 4.0.0'
6
6
  gem 'sqlite3', platforms: [:ruby]
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
9
+ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
9
10
 
10
11
  gem "rspec"
11
- gem "guard"
12
- gem "guard-rspec"
13
-
14
- gem 'coveralls', require: false
15
12
 
16
13
  platforms :rbx do
17
14
  gem 'rubysl', '~> 2.0'
data/Gemfile.rails-4.1 CHANGED
@@ -2,16 +2,13 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 4.1.4'
5
+ gem 'rails', '~> 4.1.0'
6
6
  gem 'sqlite3'
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
9
+ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
9
10
 
10
11
  gem "rspec"
11
- gem "guard"
12
- gem "guard-rspec"
13
-
14
- gem 'coveralls', require: false
15
12
 
16
13
  platforms :rbx do
17
14
  gem 'rubysl', '~> 2.0'
@@ -2,16 +2,13 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 3.0.20'
6
- gem 'sqlite3', platforms: [:ruby]
5
+ gem 'rails', '~> 4.2.0'
6
+ gem 'sqlite3'
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
9
+ gem 'tins', '~> 1.6.0', platforms: [:ruby_19]
9
10
 
10
11
  gem "rspec"
11
- gem "guard"
12
- gem "guard-rspec"
13
-
14
- gem 'coveralls', require: false
15
12
 
16
13
  platforms :rbx do
17
14
  gem 'rubysl', '~> 2.0'
@@ -2,16 +2,12 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 3.1.12'
6
- gem 'sqlite3', platforms: [:ruby]
5
+ gem 'rails', '5.0.0'
6
+ gem 'sqlite3'
7
7
  gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
8
8
  gem 'activerecord-import'
9
9
 
10
10
  gem "rspec"
11
- gem "guard"
12
- gem "guard-rspec"
13
-
14
- gem 'coveralls', require: false
15
11
 
16
12
  platforms :rbx do
17
13
  gem 'rubysl', '~> 2.0'
data/Hacking.md CHANGED
@@ -23,6 +23,7 @@ Notification instances contain the message that will be displayed, and will
23
23
  use a Presenter class to display their message to the user.
24
24
 
25
25
  So the flow of a request goes like this:
26
+
26
27
  1. Bullet.start_request is called, which resets all the detectors and empties
27
28
  the notification collector
28
29
  2. The request is handled by Rails, and the installed ActiveRecord extensions
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/bullet.png)](http://badge.fury.io/rb/bullet)
4
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)
6
5
  <a href="https://codeclimate.com/github/flyerhzm/bullet"><img src="https://codeclimate.com/github/flyerhzm/bullet.png" /></a>
7
6
  [![Coderwall Endorse](http://api.coderwall.com/flyerhzm/endorsecount.png)](http://coderwall.com/flyerhzm)
8
7
 
@@ -10,10 +9,12 @@ The Bullet gem is designed to help you increase your application's performance b
10
9
 
11
10
  Best practice is to use Bullet in development mode or custom mode (staging, profile, etc.). The last thing you want is your clients getting alerts about how lazy you are.
12
11
 
13
- Bullet gem now supports **activerecord** >= 3.0 and **mongoid** >= 2.4.1.
12
+ Bullet gem now supports **activerecord** >= 4.0 and **mongoid** >= 4.0.
14
13
 
15
14
  If you use activerecord 2.x, please use bullet <= 4.5.0
16
15
 
16
+ If you use activerecord 3.x, plesae use bullet < 5.5.0
17
+
17
18
  ## External Introduction
18
19
 
19
20
  * [http://railscasts.com/episodes/372-bullet](http://railscasts.com/episodes/372-bullet)
@@ -36,6 +37,9 @@ or add it into a Gemfile (Bundler):
36
37
  gem "bullet", :group => "development"
37
38
  ```
38
39
 
40
+ **Note**: make sure `bullet` gem is added after activerecord (rails) and
41
+ mongoid.
42
+
39
43
  ## Configuration
40
44
 
41
45
  Bullet won't do ANYTHING unless you tell it to explicitly. Append to
@@ -53,10 +57,14 @@ config.after_initialize do
53
57
  :receiver => 'your_account@jabber.org',
54
58
  :show_online_status => true }
55
59
  Bullet.rails_logger = true
60
+ Bullet.honeybadger = true
56
61
  Bullet.bugsnag = true
57
62
  Bullet.airbrake = true
63
+ Bullet.rollbar = true
58
64
  Bullet.add_footer = true
59
65
  Bullet.stacktrace_includes = [ 'your_gem', 'your_middleware' ]
66
+ Bullet.stacktrace_excludes = [ 'their_gem', 'their_middleware' ]
67
+ Bullet.slack = { webhook_url: 'http://some.slack.url', channel: '#default', username: 'notifier' }
60
68
  end
61
69
  ```
62
70
 
@@ -67,13 +75,18 @@ The code above will enable all seven of the Bullet notification systems:
67
75
  * `Bullet.alert`: pop up a JavaScript alert in the browser
68
76
  * `Bullet.bullet_logger`: log to the Bullet log file (Rails.root/log/bullet.log)
69
77
  * `Bullet.rails_logger`: add warnings directly to the Rails log
78
+ * `Bullet.honeybadger`: add notifications to Honeybadger
79
+ * `Bullet.bugsnag`: add notifications to bugsnag
70
80
  * `Bullet.airbrake`: add notifications to airbrake
81
+ * `Bullet.rollbar`: add notifications to rollbar
71
82
  * `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
72
83
  * `Bullet.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
73
84
  * `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.
74
85
  * `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
75
- * `Bullet.add_footer`: adds the details in the bottom left corner of the page
86
+ * `Bullet.add_footer`: adds the details in the bottom left corner of the page. Double click the footer or use close button to hide footer.
76
87
  * `Bullet.stacktrace_includes`: include paths with any of these substrings in the stack trace, even if they are not in your main app
88
+ * `Bullet.stacktrace_excludes`: ignore paths with any of these substrings in the stack trace, even if they are not in your main app.
89
+ * `Bullet.slack`: add notifications to slack
77
90
 
78
91
  Bullet also allows you to disable any of its detectors.
79
92
 
@@ -102,6 +115,22 @@ Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :ass
102
115
  Bullet.add_whitelist :type => :counter_cache, :class_name => "Country", :association => :cities
103
116
  ```
104
117
 
118
+ If you want to skip bullet in some specific controller actions, you can
119
+ do like
120
+
121
+ ```ruby
122
+ class ApplicationController < ActionController::Base
123
+ around_action :skip_bullet
124
+
125
+ def skip_bullet
126
+ Bullet.enable = false
127
+ yield
128
+ ensure
129
+ Bullet.enable = true
130
+ end
131
+ end
132
+ ```
133
+
105
134
  ## Log
106
135
 
107
136
  The Bullet log `log/bullet.log` will look something like this:
@@ -153,8 +182,9 @@ The Bullet gem uses rack middleware to profile requests. If you want to use Bull
153
182
  ```ruby
154
183
  Bullet.profile do
155
184
  # do anything
185
+
186
+ warnings = Bullet.warnings
156
187
  end
157
- warnings = Bullet.warnings
158
188
  ```
159
189
 
160
190
  ### Work with sinatra
@@ -209,7 +239,9 @@ Bullet outputs some details info, to enable debug mode, set
209
239
 
210
240
  ## Demo
211
241
 
212
- Bullet is designed to function as you browse through your application in development. To see it in action, follow these steps to create, detect, and fix example query problems.
242
+ Bullet is designed to function as you browse through your application in development. To see it in action,
243
+ you can visit [https://github.com/flyerhzm/bullet_test](https://github.com/flyerhzm/bullet_test) or
244
+ follow these steps to create, detect, and fix example query problems.
213
245
 
214
246
  1\. Create an example application
215
247
 
@@ -302,7 +334,7 @@ model: Post => associations: [comment]
302
334
 
303
335
  which means there is a N+1 query from the Post object to its Comment association.
304
336
 
305
- In the meanwhile, there's a log appended into `log/bullet.log` file
337
+ In the meantime, there's a log appended into `log/bullet.log` file
306
338
 
307
339
  ```
308
340
  2010-03-07 14:12:18[INFO] N+1 Query in /posts
@@ -429,4 +461,4 @@ Meanwhile, there's a line appended to `log/bullet.log`
429
461
  Post => [:comments]
430
462
  ```
431
463
 
432
- Copyright (c) 2009 - 2014 Richard Huang (flyerhzm@gmail.com), released under the MIT license
464
+ Copyright (c) 2009 - 2016 Richard Huang (flyerhzm@gmail.com), released under the MIT license
data/bullet.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.required_rubygems_version = ">= 1.3.6"
19
19
 
20
20
  s.add_runtime_dependency "activesupport", ">= 3.0.0"
21
- s.add_runtime_dependency "uniform_notifier", ">= 1.6.0"
21
+ s.add_runtime_dependency "uniform_notifier", "~> 1.10.0"
22
22
 
23
23
  s.files = `git ls-files`.split("\n")
24
24
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -2,35 +2,81 @@ module Bullet
2
2
  module ActiveRecord
3
3
  def self.enable
4
4
  require 'active_record'
5
+ ::ActiveRecord::Base.class_eval do
6
+ class <<self
7
+ alias_method :origin_find_by_sql, :find_by_sql
8
+ def find_by_sql(sql, binds = [])
9
+ result = origin_find_by_sql(sql, binds)
10
+ if Bullet.start?
11
+ if result.is_a? Array
12
+ if result.size > 1
13
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
14
+ Bullet::Detector::CounterCache.add_possible_objects(result)
15
+ elsif result.size == 1
16
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
17
+ Bullet::Detector::CounterCache.add_impossible_object(result.first)
18
+ end
19
+ elsif result.is_a? ::ActiveRecord::Base
20
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
21
+ Bullet::Detector::CounterCache.add_impossible_object(result)
22
+ end
23
+ end
24
+ result
25
+ end
26
+ end
27
+ end
28
+
5
29
  ::ActiveRecord::Relation.class_eval do
6
30
  alias_method :origin_to_a, :to_a
7
31
  # if select a collection of objects, then these objects have possible to cause N+1 query.
8
32
  # if select only one object, then the only one object has impossible to cause N+1 query.
9
33
  def to_a
10
34
  records = origin_to_a
11
- if records.size > 1
12
- Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
13
- Bullet::Detector::CounterCache.add_possible_objects(records)
14
- elsif records.size == 1
15
- Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
16
- Bullet::Detector::CounterCache.add_impossible_object(records.first)
35
+ if Bullet.start?
36
+ if records.size > 1
37
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
38
+ Bullet::Detector::CounterCache.add_possible_objects(records)
39
+ elsif records.size == 1
40
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
41
+ Bullet::Detector::CounterCache.add_impossible_object(records.first)
42
+ end
17
43
  end
18
44
  records
19
45
  end
20
46
  end
21
47
 
48
+ ::ActiveRecord::Persistence.class_eval do
49
+ def save_with_bullet(*args, &proc)
50
+ was_new_record = new_record?
51
+ save_without_bullet(*args, &proc).tap do |result|
52
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
53
+ end
54
+ end
55
+ alias_method_chain :save, :bullet
56
+
57
+ def save_with_bullet!(*args, &proc)
58
+ was_new_record = new_record?
59
+ save_without_bullet!(*args, &proc).tap do |result|
60
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
61
+ end
62
+ end
63
+ alias_method_chain :save!, :bullet
64
+ end
65
+
22
66
  ::ActiveRecord::Associations::Preloader.class_eval do
23
67
  # include query for one to many associations.
24
68
  # keep this eager loadings.
25
69
  alias_method :origin_initialize, :initialize
26
70
  def initialize(records, associations, preload_scope = nil)
27
71
  origin_initialize(records, associations, preload_scope)
28
- records = [records].flatten.compact.uniq
29
- return if records.empty?
30
- records.each do |record|
31
- Bullet::Detector::Association.add_object_associations(record, associations)
72
+ if Bullet.start?
73
+ records = [records].flatten.compact.uniq
74
+ return if records.empty?
75
+ records.each do |record|
76
+ Bullet::Detector::Association.add_object_associations(record, associations)
77
+ end
78
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
32
79
  end
33
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
34
80
  end
35
81
  end
36
82
 
@@ -39,11 +85,13 @@ module Bullet
39
85
  alias_method :origin_find_with_associations, :find_with_associations
40
86
  def find_with_associations
41
87
  records = origin_find_with_associations
42
- associations = (eager_load_values + includes_values).uniq
43
- records.each do |record|
44
- Bullet::Detector::Association.add_object_associations(record, associations)
88
+ if Bullet.start?
89
+ associations = (eager_load_values + includes_values).uniq
90
+ records.each do |record|
91
+ Bullet::Detector::Association.add_object_associations(record, associations)
92
+ end
93
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
45
94
  end
46
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
47
95
  records
48
96
  end
49
97
  end
@@ -56,9 +104,11 @@ module Bullet
56
104
  @bullet_eager_loadings = {}
57
105
  records = origin_instantiate(rows)
58
106
 
59
- @bullet_eager_loadings.each do |klazz, eager_loadings_hash|
60
- objects = eager_loadings_hash.keys
61
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
107
+ if Bullet.start?
108
+ @bullet_eager_loadings.each do |klazz, eager_loadings_hash|
109
+ objects = eager_loadings_hash.keys
110
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
111
+ end
62
112
  end
63
113
  records
64
114
  end
@@ -67,12 +117,14 @@ module Bullet
67
117
  def construct_association(record, join, row)
68
118
  result = origin_construct_association(record, join, row)
69
119
 
70
- associations = join.reflection.name
71
- Bullet::Detector::Association.add_object_associations(record, associations)
72
- Bullet::Detector::NPlusOneQuery.call_association(record, associations)
73
- @bullet_eager_loadings[record.class] ||= {}
74
- @bullet_eager_loadings[record.class][record] ||= Set.new
75
- @bullet_eager_loadings[record.class][record] << associations
120
+ if Bullet.start?
121
+ associations = join.reflection.name
122
+ Bullet::Detector::Association.add_object_associations(record, associations)
123
+ Bullet::Detector::NPlusOneQuery.call_association(record, associations)
124
+ @bullet_eager_loadings[record.class] ||= {}
125
+ @bullet_eager_loadings[record.class][record] ||= Set.new
126
+ @bullet_eager_loadings[record.class][record] << associations
127
+ end
76
128
 
77
129
  result
78
130
  end
@@ -82,20 +134,38 @@ module Bullet
82
134
  # call one to many associations
83
135
  alias_method :origin_load_target, :load_target
84
136
  def load_target
85
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
137
+ if Bullet.start?
138
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
139
+ end
86
140
  origin_load_target
87
141
  end
88
142
 
143
+ alias_method :origin_include?, :include?
144
+ def include?(object)
145
+ if Bullet.start?
146
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
147
+ end
148
+ origin_include?(object)
149
+ end
150
+ end
151
+
152
+ ::ActiveRecord::Associations::HasManyAssociation.class_eval do
89
153
  alias_method :origin_empty?, :empty?
90
154
  def empty?
91
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
155
+ if Bullet.start? && !loaded? && !has_cached_counter?(@reflection)
156
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
157
+ end
92
158
  origin_empty?
93
159
  end
160
+ end
94
161
 
95
- alias_method :origin_include?, :include?
96
- def include?(object)
97
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
98
- origin_include?(object)
162
+ ::ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
163
+ alias_method :origin_empty?, :empty?
164
+ def empty?
165
+ if Bullet.start? && !loaded?
166
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
167
+ end
168
+ origin_empty?
99
169
  end
100
170
  end
101
171
 
@@ -104,8 +174,12 @@ module Bullet
104
174
  alias_method :origin_reader, :reader
105
175
  def reader(force_reload = false)
106
176
  result = origin_reader(force_reload)
107
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless @inversed
108
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
177
+ if Bullet.start?
178
+ unless @inversed
179
+ Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
180
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
181
+ end
182
+ end
109
183
  result
110
184
  end
111
185
  end
@@ -115,7 +189,9 @@ module Bullet
115
189
 
116
190
  def has_cached_counter?(reflection = reflection())
117
191
  result = origin_has_cached_counter?(reflection)
118
- Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name) unless result
192
+ if Bullet.start? && !result
193
+ Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
194
+ end
119
195
  result
120
196
  end
121
197
  end