bullet 6.1.0 → 7.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +101 -2
- data/MIT-LICENSE +1 -1
- data/README.md +48 -30
- data/lib/bullet/active_job.rb +5 -1
- data/lib/bullet/active_record4.rb +21 -6
- data/lib/bullet/active_record41.rb +22 -6
- data/lib/bullet/active_record42.rb +33 -12
- data/lib/bullet/active_record5.rb +50 -20
- data/lib/bullet/active_record52.rb +71 -36
- data/lib/bullet/active_record60.rb +70 -35
- data/lib/bullet/active_record61.rb +302 -0
- data/lib/bullet/active_record70.rb +318 -0
- data/lib/bullet/active_record71.rb +318 -0
- data/lib/bullet/bullet_xhr.js +18 -17
- data/lib/bullet/dependency.rb +28 -0
- data/lib/bullet/detector/association.rb +8 -0
- data/lib/bullet/detector/base.rb +2 -1
- data/lib/bullet/detector/counter_cache.rb +2 -2
- data/lib/bullet/detector/n_plus_one_query.rb +21 -13
- data/lib/bullet/detector/unused_eager_loading.rb +6 -3
- data/lib/bullet/ext/object.rb +14 -3
- data/lib/bullet/mongoid4x.rb +1 -1
- data/lib/bullet/mongoid5x.rb +1 -1
- data/lib/bullet/mongoid6x.rb +1 -1
- data/lib/bullet/mongoid7x.rb +32 -17
- data/lib/bullet/mongoid8x.rb +59 -0
- data/lib/bullet/notification/base.rb +22 -10
- data/lib/bullet/notification/counter_cache.rb +1 -1
- data/lib/bullet/notification.rb +2 -1
- data/lib/bullet/rack.rb +67 -24
- data/lib/bullet/registry/association.rb +2 -1
- data/lib/bullet/registry/call_stack.rb +12 -0
- data/lib/bullet/registry.rb +1 -0
- data/lib/bullet/stack_trace_filter.rb +16 -15
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +45 -30
- data/lib/generators/bullet/install_generator.rb +22 -25
- metadata +13 -148
- data/.gitignore +0 -15
- data/.rspec +0 -2
- data/.travis.yml +0 -33
- data/Gemfile +0 -24
- data/Gemfile.mongoid +0 -12
- data/Gemfile.mongoid-4.0 +0 -15
- data/Gemfile.mongoid-5.0 +0 -15
- data/Gemfile.mongoid-6.0 +0 -15
- data/Gemfile.mongoid-7.0 +0 -15
- data/Gemfile.rails-4.0 +0 -16
- data/Gemfile.rails-4.1 +0 -16
- data/Gemfile.rails-4.2 +0 -16
- data/Gemfile.rails-5.0 +0 -15
- data/Gemfile.rails-5.1 +0 -15
- data/Gemfile.rails-5.2 +0 -15
- data/Gemfile.rails-6.0 +0 -15
- data/Guardfile +0 -8
- data/Hacking.md +0 -75
- data/Rakefile +0 -51
- data/bullet.gemspec +0 -33
- data/perf/benchmark.rb +0 -115
- data/rails/init.rb +0 -3
- data/spec/bullet/detector/association_spec.rb +0 -28
- data/spec/bullet/detector/base_spec.rb +0 -10
- data/spec/bullet/detector/counter_cache_spec.rb +0 -58
- data/spec/bullet/detector/n_plus_one_query_spec.rb +0 -182
- data/spec/bullet/detector/unused_eager_loading_spec.rb +0 -121
- data/spec/bullet/ext/object_spec.rb +0 -44
- data/spec/bullet/ext/string_spec.rb +0 -15
- data/spec/bullet/notification/base_spec.rb +0 -94
- data/spec/bullet/notification/counter_cache_spec.rb +0 -14
- data/spec/bullet/notification/n_plus_one_query_spec.rb +0 -31
- data/spec/bullet/notification/unused_eager_loading_spec.rb +0 -18
- data/spec/bullet/notification_collector_spec.rb +0 -34
- data/spec/bullet/rack_spec.rb +0 -153
- data/spec/bullet/registry/association_spec.rb +0 -28
- data/spec/bullet/registry/base_spec.rb +0 -46
- data/spec/bullet/registry/object_spec.rb +0 -26
- data/spec/bullet_spec.rb +0 -136
- data/spec/integration/active_record/association_spec.rb +0 -739
- data/spec/integration/counter_cache_spec.rb +0 -68
- data/spec/integration/mongoid/association_spec.rb +0 -246
- data/spec/models/address.rb +0 -5
- data/spec/models/author.rb +0 -5
- data/spec/models/base_user.rb +0 -7
- data/spec/models/category.rb +0 -12
- data/spec/models/city.rb +0 -5
- data/spec/models/client.rb +0 -8
- data/spec/models/comment.rb +0 -8
- data/spec/models/company.rb +0 -5
- data/spec/models/country.rb +0 -5
- data/spec/models/document.rb +0 -7
- data/spec/models/entry.rb +0 -5
- data/spec/models/firm.rb +0 -7
- data/spec/models/folder.rb +0 -3
- data/spec/models/group.rb +0 -3
- data/spec/models/mongoid/address.rb +0 -9
- data/spec/models/mongoid/category.rb +0 -10
- data/spec/models/mongoid/comment.rb +0 -9
- data/spec/models/mongoid/company.rb +0 -9
- data/spec/models/mongoid/entry.rb +0 -9
- data/spec/models/mongoid/post.rb +0 -14
- data/spec/models/mongoid/user.rb +0 -7
- data/spec/models/newspaper.rb +0 -5
- data/spec/models/page.rb +0 -3
- data/spec/models/person.rb +0 -5
- data/spec/models/pet.rb +0 -5
- data/spec/models/post.rb +0 -32
- data/spec/models/relationship.rb +0 -6
- data/spec/models/reply.rb +0 -5
- data/spec/models/student.rb +0 -5
- data/spec/models/submission.rb +0 -6
- data/spec/models/teacher.rb +0 -5
- data/spec/models/user.rb +0 -6
- data/spec/models/writer.rb +0 -3
- data/spec/spec_helper.rb +0 -99
- data/spec/support/bullet_ext.rb +0 -56
- data/spec/support/mongo_seed.rb +0 -58
- data/spec/support/rack_double.rb +0 -49
- data/spec/support/sqlite_seed.rb +0 -246
- data/test.sh +0 -13
- data/update.sh +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 752fed6e96f9ea5c1baefca2e9a80ea3aefa13c279d24688f3341d18c8334afc
|
4
|
+
data.tar.gz: 78edabbca2c71e9c6d2c793bd3786d5b826f4530664aa18e7cd42cb059a85373
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cad943f3641de44f17da3fe2062ed83525d0bbb1d4321208f55b4d05d6a43840f25fe0728fa4e10f42701dd8ef4eaa2322ca9ab8c8d6a2e7d7067c70d0d3186
|
7
|
+
data.tar.gz: a58309dcbfaadbb9f67352c0a1730be8397c2522ef403093fcf58a8fdcc596b45e961d39b239e40412d46d98a50033ed02398efc70df4314631bd16e220a7c88
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,104 @@
|
|
1
1
|
## Next Release
|
2
2
|
|
3
|
+
## 7.1.6 (01/16/2024)
|
4
|
+
|
5
|
+
* Allow apps to not include the user in a notification
|
6
|
+
|
7
|
+
## 7.1.5 (01/05/2024)
|
8
|
+
|
9
|
+
* Fix mongoid8
|
10
|
+
|
11
|
+
## 7.1.4 (11/17/2023)
|
12
|
+
|
13
|
+
* Call association also on through reflection
|
14
|
+
|
15
|
+
## 7.1.3 (11/05/2023)
|
16
|
+
|
17
|
+
* Call NPlusOneQuery's call_association when calling count on collection association
|
18
|
+
|
19
|
+
## 7.1.2 (10/13/2023)
|
20
|
+
|
21
|
+
* Handle Rails 7.1 composite primary keys
|
22
|
+
|
23
|
+
## 7.1.1 (10/07/2023)
|
24
|
+
|
25
|
+
* Add support for `Content-Security-Policy-Report-Only` nonces
|
26
|
+
* Fix count method signature
|
27
|
+
|
28
|
+
## 7.1.0 (10/06/2023)
|
29
|
+
|
30
|
+
* Support rails 7.1
|
31
|
+
* Alias `Bullet.enable?` to `enabled?`, and `Bullet.enable=` to `enabled=`
|
32
|
+
* Added `always_append_html_body` option, so the html snippet is always included even if there are no notifications
|
33
|
+
* Added detection of n+1 count queries from `count` method
|
34
|
+
* Changed the counter cache notification title to recommend using `size`
|
35
|
+
|
36
|
+
## 7.0.7 (03/01/2023)
|
37
|
+
|
38
|
+
* Check `Rails.application.config.content_security_policy` before insert `Bullet::Rack`
|
39
|
+
|
40
|
+
## 7.0.6 (03/01/2023)
|
41
|
+
|
42
|
+
* Better way to check if `ActionDispatch::ContentSecurityPolicy::Middleware` exists
|
43
|
+
|
44
|
+
## 7.0.5 (01/01/2023)
|
45
|
+
|
46
|
+
* Fix n+1 false positives in AR 7.0
|
47
|
+
* Fix eager_load nested has_many :through false positives
|
48
|
+
* Respect Content-Security-Policy nonces
|
49
|
+
* Added CallStacks support for avoid eager loading
|
50
|
+
* Iterate fewer times over objects
|
51
|
+
|
52
|
+
## 7.0.4 (11/28/2022)
|
53
|
+
|
54
|
+
* Fix `eager_load` `has_many :through` false positives
|
55
|
+
* mongoid7x: add dynamic methods
|
56
|
+
|
57
|
+
## 7.0.3 (08/13/2022)
|
58
|
+
|
59
|
+
* Replace `Array()` with `Array.wrap()`
|
60
|
+
|
61
|
+
## 7.0.2 (05/31/2022)
|
62
|
+
|
63
|
+
* Drop growl support
|
64
|
+
* Do not check html tag in Bullet::Rack anymore
|
65
|
+
|
66
|
+
## 7.0.1 (01/15/2022)
|
67
|
+
|
68
|
+
* Get rid of *_whitelist methods
|
69
|
+
* Hack ActiveRecord::Associations::Preloader::Batch in rails 7
|
70
|
+
|
71
|
+
## 7.0.0 (12/18/2021)
|
72
|
+
|
73
|
+
* Support rails 7
|
74
|
+
* Fix Mongoid 7 view iteration
|
75
|
+
* Move CI from Travis to Github Actions
|
76
|
+
|
77
|
+
## 6.1.5 (08/16/2021)
|
78
|
+
|
79
|
+
* Rename whitelist to safelist
|
80
|
+
* Fix onload called twice
|
81
|
+
* Support Rack::Files::Iterator responses
|
82
|
+
* Ensure HABTM associations are not incorrectly labeled n+1
|
83
|
+
|
84
|
+
## 6.1.4 (02/26/2021)
|
85
|
+
|
86
|
+
* Added an option to stop adding HTTP headers to API requests
|
87
|
+
|
88
|
+
## 6.1.3 (01/21/2021)
|
89
|
+
|
90
|
+
* Consider ThroughAssociation at SingularAssociation like CollectionAssociation
|
91
|
+
* Add xhr_script only when add_footer is enabled
|
92
|
+
|
93
|
+
## 6.1.2 (12/12/2020)
|
94
|
+
|
95
|
+
* Revert "Make whitelist thread safe"
|
96
|
+
|
97
|
+
## 6.1.1 (12/12/2020)
|
98
|
+
|
99
|
+
* Add support Rails 6.1
|
100
|
+
* Make whitelist thread safe
|
101
|
+
|
3
102
|
## 6.1.0 (12/28/2019)
|
4
103
|
|
5
104
|
* Add skip_html_injection flag
|
@@ -31,7 +130,7 @@
|
|
31
130
|
|
32
131
|
* Fix through reflection for rails 5.x
|
33
132
|
* Fix false positive in after_save/after_create callbacks
|
34
|
-
* Don't
|
133
|
+
* Don't trigger a preload error on "manual" preloads
|
35
134
|
* Avoid Bullet from making extra queries in mongoid6
|
36
135
|
* Support option for #first and #last on mongoid6.x
|
37
136
|
* Fix duplicate logs in mongoid 4.x and 5.x version
|
@@ -173,7 +272,7 @@
|
|
173
272
|
|
174
273
|
## 4.5.0 (03/24/2013)
|
175
274
|
|
176
|
-
* Add api way to access captured
|
275
|
+
* Add api way to access captured association
|
177
276
|
* Allow disable n_plus_one_query, unused_eager_loading and counter_cache respectively
|
178
277
|
* Add whitelist
|
179
278
|
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Bullet
|
2
2
|
|
3
|
+
![Main workflow](https://github.com/flyerhzm/bullet/actions/workflows/main.yml/badge.svg)
|
3
4
|
[![Gem Version](https://badge.fury.io/rb/bullet.svg)](http://badge.fury.io/rb/bullet)
|
4
|
-
[![Build Status](https://secure.travis-ci.org/flyerhzm/bullet.svg)](http://travis-ci.org/flyerhzm/bullet)
|
5
5
|
[![AwesomeCode Status for flyerhzm/bullet](https://awesomecode.io/projects/6755235b-e2c1-459e-bf92-b8b13d0c0472/status)](https://awesomecode.io/repos/flyerhzm/bullet)
|
6
6
|
[![Coderwall Endorse](http://api.coderwall.com/flyerhzm/endorsecount.png)](http://coderwall.com/flyerhzm)
|
7
7
|
|
@@ -37,12 +37,19 @@ or add it into a Gemfile (Bundler):
|
|
37
37
|
gem 'bullet', group: 'development'
|
38
38
|
```
|
39
39
|
|
40
|
+
enable the Bullet gem with generate command
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
bundle exec rails g bullet:install
|
44
|
+
```
|
45
|
+
The generate command will auto generate the default configuration and may ask to include in the test environment as well. See below for custom configuration.
|
46
|
+
|
40
47
|
**Note**: make sure `bullet` gem is added after activerecord (rails) and
|
41
48
|
mongoid.
|
42
49
|
|
43
50
|
## Configuration
|
44
51
|
|
45
|
-
Bullet won't
|
52
|
+
Bullet won't enable any notification systems unless you tell it to explicitly. Append to
|
46
53
|
`config/environments/development.rb` initializer with the following code:
|
47
54
|
|
48
55
|
```ruby
|
@@ -52,7 +59,6 @@ config.after_initialize do
|
|
52
59
|
Bullet.alert = true
|
53
60
|
Bullet.bullet_logger = true
|
54
61
|
Bullet.console = true
|
55
|
-
Bullet.growl = true
|
56
62
|
Bullet.xmpp = { :account => 'bullets_account@jabber.org',
|
57
63
|
:password => 'bullets_password_for_jabber',
|
58
64
|
:receiver => 'your_account@jabber.org',
|
@@ -60,6 +66,7 @@ config.after_initialize do
|
|
60
66
|
Bullet.rails_logger = true
|
61
67
|
Bullet.honeybadger = true
|
62
68
|
Bullet.bugsnag = true
|
69
|
+
Bullet.appsignal = true
|
63
70
|
Bullet.airbrake = true
|
64
71
|
Bullet.rollbar = true
|
65
72
|
Bullet.add_footer = true
|
@@ -77,22 +84,25 @@ The code above will enable all of the Bullet notification systems:
|
|
77
84
|
* `Bullet.alert`: pop up a JavaScript alert in the browser
|
78
85
|
* `Bullet.bullet_logger`: log to the Bullet log file (Rails.root/log/bullet.log)
|
79
86
|
* `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
|
80
|
-
* `Bullet.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
|
81
87
|
* `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.
|
82
88
|
* `Bullet.rails_logger`: add warnings directly to the Rails log
|
83
89
|
* `Bullet.honeybadger`: add notifications to Honeybadger
|
84
90
|
* `Bullet.bugsnag`: add notifications to bugsnag
|
85
91
|
* `Bullet.airbrake`: add notifications to airbrake
|
92
|
+
* `Bullet.appsignal`: add notifications to AppSignal
|
86
93
|
* `Bullet.rollbar`: add notifications to rollbar
|
87
94
|
* `Bullet.sentry`: add notifications to sentry
|
88
95
|
* `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.
|
89
|
-
* `Bullet.skip_html_injection`: prevents Bullet from injecting
|
96
|
+
* `Bullet.skip_html_injection`: prevents Bullet from injecting code into the returned HTML. This must be false for receiving alerts, showing the footer or console logging.
|
97
|
+
* `Bullet.skip_http_headers`: don't add headers to API requests, and remove the javascript that relies on them. Note that this prevents bullet from logging warnings to the browser console or updating the footer.
|
90
98
|
* `Bullet.stacktrace_includes`: include paths with any of these substrings in the stack trace, even if they are not in your main app
|
91
99
|
* `Bullet.stacktrace_excludes`: ignore paths with any of these substrings in the stack trace, even if they are not in your main app.
|
92
100
|
Each item can be a string (match substring), a regex, or an array where the first item is a path to match, and the second
|
93
101
|
item is a line number, a Range of line numbers, or a (bare) method name, to exclude only particular lines in a file.
|
94
102
|
* `Bullet.slack`: add notifications to slack
|
95
103
|
* `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
|
104
|
+
* `Bullet.always_append_html_body`: always append the html body even if no notifications are present. Note: `console` or `add_footer` must also be true. Useful for Single Page Applications where the initial page load might not have any notifications present.
|
105
|
+
* `Bullet.skip_user_in_notification`: exclude the OS user (`whoami`) from notifications.
|
96
106
|
|
97
107
|
|
98
108
|
Bullet also allows you to disable any of its detectors.
|
@@ -111,15 +121,17 @@ Bullet.unused_eager_loading_enable = false
|
|
111
121
|
Bullet.counter_cache_enable = false
|
112
122
|
```
|
113
123
|
|
114
|
-
|
124
|
+
Note: When calling `Bullet.enable`, all other detectors are reset to their defaults (`true`) and need reconfiguring.
|
125
|
+
|
126
|
+
## Safe list
|
115
127
|
|
116
128
|
Sometimes Bullet may notify you of query problems you don't care to fix, or
|
117
|
-
which come from outside your code. You can
|
129
|
+
which come from outside your code. You can add them to a safe list to ignore them:
|
118
130
|
|
119
131
|
```ruby
|
120
|
-
Bullet.
|
121
|
-
Bullet.
|
122
|
-
Bullet.
|
132
|
+
Bullet.add_safelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments
|
133
|
+
Bullet.add_safelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments
|
134
|
+
Bullet.add_safelist :type => :counter_cache, :class_name => "Country", :association => :cities
|
123
135
|
```
|
124
136
|
|
125
137
|
If you want to skip bullet in some specific controller actions, you can
|
@@ -146,25 +158,26 @@ The Bullet log `log/bullet.log` will look something like this:
|
|
146
158
|
* N+1 Query:
|
147
159
|
|
148
160
|
```
|
149
|
-
2009-08-25 20:40:17[INFO]
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
/Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `each'
|
154
|
-
/Users/richard/Downloads/test/app/
|
155
|
-
/Users/richard/Downloads/test/app/controllers/posts_controller.rb:7:in `index'
|
161
|
+
2009-08-25 20:40:17[INFO] USE eager loading detected:
|
162
|
+
Post => [:comments]·
|
163
|
+
Add to your query: .includes([:comments])
|
164
|
+
2009-08-25 20:40:17[INFO] Call stack
|
165
|
+
/Users/richard/Downloads/test/app/views/posts/index.html.erb:8:in `each'
|
166
|
+
/Users/richard/Downloads/test/app/controllers/posts_controller.rb:7:in `index'
|
156
167
|
```
|
157
168
|
|
158
|
-
The first
|
169
|
+
The first log entry is a notification that N+1 queries have been encountered. The remaining entry is a stack trace so you can find exactly where the queries were invoked in your code, and fix them.
|
159
170
|
|
160
171
|
* Unused eager loading:
|
161
172
|
|
162
173
|
```
|
163
|
-
2009-08-25 20:53:56[INFO]
|
164
|
-
|
174
|
+
2009-08-25 20:53:56[INFO] AVOID eager loading detected
|
175
|
+
Post => [:comments]·
|
176
|
+
Remove from your query: .includes([:comments])
|
177
|
+
2009-08-25 20:53:56[INFO] Call stack
|
165
178
|
```
|
166
179
|
|
167
|
-
These
|
180
|
+
These lines are notifications that unused eager loadings have been encountered.
|
168
181
|
|
169
182
|
* Need counter cache:
|
170
183
|
|
@@ -173,10 +186,14 @@ These two lines are notifications that unused eager loadings have been encounter
|
|
173
186
|
Post => [:comments]
|
174
187
|
```
|
175
188
|
|
176
|
-
##
|
189
|
+
## XMPP/Jabber and Airbrake Support
|
177
190
|
|
178
191
|
see [https://github.com/flyerhzm/uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
|
179
192
|
|
193
|
+
## Growl Support
|
194
|
+
|
195
|
+
Growl support is dropped from uniform_notifier 1.16.0, if you still want it, please use uniform_notifier 1.15.0.
|
196
|
+
|
180
197
|
## Important
|
181
198
|
|
182
199
|
If you find Bullet does not work for you, *please disable your browser's cache*.
|
@@ -209,7 +226,7 @@ end
|
|
209
226
|
|
210
227
|
### Work with sinatra
|
211
228
|
|
212
|
-
Configure and use `Bullet::Rack
|
229
|
+
Configure and use `Bullet::Rack`.
|
213
230
|
|
214
231
|
```ruby
|
215
232
|
configure :development do
|
@@ -219,6 +236,8 @@ configure :development do
|
|
219
236
|
end
|
220
237
|
```
|
221
238
|
|
239
|
+
If your application generates a Content-Security-Policy via a separate middleware, ensure that `Bullet::Rack` is loaded _before_ that middleware.
|
240
|
+
|
222
241
|
### Run in tests
|
223
242
|
|
224
243
|
First you need to enable Bullet in test environment.
|
@@ -260,8 +279,7 @@ Bullet outputs some details info, to enable debug mode, set
|
|
260
279
|
## Demo
|
261
280
|
|
262
281
|
Bullet is designed to function as you browse through your application in development. To see it in action,
|
263
|
-
you can
|
264
|
-
follow these steps to create, detect, and fix example query problems.
|
282
|
+
you can follow these steps to create, detect, and fix example query problems.
|
265
283
|
|
266
284
|
1\. Create an example application
|
267
285
|
|
@@ -270,17 +288,17 @@ $ rails new test_bullet
|
|
270
288
|
$ cd test_bullet
|
271
289
|
$ rails g scaffold post name:string
|
272
290
|
$ rails g scaffold comment name:string post_id:integer
|
273
|
-
$ bundle exec
|
291
|
+
$ bundle exec rails db:migrate
|
274
292
|
```
|
275
293
|
|
276
|
-
2\. Change `app/
|
294
|
+
2\. Change `app/models/post.rb` and `app/models/comment.rb`
|
277
295
|
|
278
296
|
```ruby
|
279
|
-
class Post <
|
297
|
+
class Post < ApplicationRecord
|
280
298
|
has_many :comments
|
281
299
|
end
|
282
300
|
|
283
|
-
class Comment <
|
301
|
+
class Comment < ApplicationRecord
|
284
302
|
belongs_to :post
|
285
303
|
end
|
286
304
|
```
|
@@ -472,4 +490,4 @@ Meanwhile, there's a line appended to `log/bullet.log`
|
|
472
490
|
Post => [:comments]
|
473
491
|
```
|
474
492
|
|
475
|
-
Copyright (c) 2009 -
|
493
|
+
Copyright (c) 2009 - 2022 Richard Huang (flyerhzm@gmail.com), released under the MIT license
|
data/lib/bullet/active_job.rb
CHANGED
@@ -3,7 +3,11 @@
|
|
3
3
|
module Bullet
|
4
4
|
module ActiveJob
|
5
5
|
def self.included(base)
|
6
|
-
base.class_eval
|
6
|
+
base.class_eval do
|
7
|
+
around_perform do |_job, block|
|
8
|
+
Bullet.profile { block.call }
|
9
|
+
end
|
10
|
+
end
|
7
11
|
end
|
8
12
|
end
|
9
13
|
end
|
@@ -107,12 +107,17 @@ module Bullet
|
|
107
107
|
result = origin_construct_association(record, join, row)
|
108
108
|
|
109
109
|
if Bullet.start?
|
110
|
-
associations = join.reflection.name
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
110
|
+
associations = [join.reflection.name]
|
111
|
+
if join.reflection.nested?
|
112
|
+
associations << join.reflection.through_reflection.name
|
113
|
+
end
|
114
|
+
associations.each do |association|
|
115
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
116
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, association)
|
117
|
+
@bullet_eager_loadings[record.class] ||= {}
|
118
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
119
|
+
@bullet_eager_loadings[record.class][record] << association
|
120
|
+
end
|
116
121
|
end
|
117
122
|
|
118
123
|
result
|
@@ -176,6 +181,16 @@ module Bullet
|
|
176
181
|
result
|
177
182
|
end
|
178
183
|
end
|
184
|
+
|
185
|
+
::ActiveRecord::Associations::CollectionProxy.class_eval do
|
186
|
+
def count(column_name = nil, options = {})
|
187
|
+
if Bullet.start?
|
188
|
+
Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
|
189
|
+
Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
|
190
|
+
end
|
191
|
+
super(column_name, options)
|
192
|
+
end
|
193
|
+
end
|
179
194
|
end
|
180
195
|
end
|
181
196
|
end
|
@@ -30,6 +30,7 @@ module Bullet
|
|
30
30
|
|
31
31
|
::ActiveRecord::Relation.class_eval do
|
32
32
|
alias_method :origin_to_a, :to_a
|
33
|
+
|
33
34
|
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
34
35
|
# if select only one object, then the only one object has impossible to cause N+1 query.
|
35
36
|
def to_a
|
@@ -109,12 +110,17 @@ module Bullet
|
|
109
110
|
result = origin_construct_model(record, node, row, model_cache, id, aliases)
|
110
111
|
|
111
112
|
if Bullet.start?
|
112
|
-
associations = node.reflection.name
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
113
|
+
associations = [node.reflection.name]
|
114
|
+
if node.reflection.nested?
|
115
|
+
associations << node.reflection.through_reflection.name
|
116
|
+
end
|
117
|
+
associations.each do |association|
|
118
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
119
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, association)
|
120
|
+
@bullet_eager_loadings[record.class] ||= {}
|
121
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
122
|
+
@bullet_eager_loadings[record.class][record] << association
|
123
|
+
end
|
118
124
|
end
|
119
125
|
|
120
126
|
result
|
@@ -167,6 +173,16 @@ module Bullet
|
|
167
173
|
origin_count_records
|
168
174
|
end
|
169
175
|
end
|
176
|
+
|
177
|
+
::ActiveRecord::Associations::CollectionProxy.class_eval do
|
178
|
+
def count(column_name = nil, options = {})
|
179
|
+
if Bullet.start?
|
180
|
+
Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
|
181
|
+
Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
|
182
|
+
end
|
183
|
+
super(column_name, options)
|
184
|
+
end
|
185
|
+
end
|
170
186
|
end
|
171
187
|
end
|
172
188
|
end
|
@@ -52,6 +52,7 @@ module Bullet
|
|
52
52
|
|
53
53
|
::ActiveRecord::Relation.class_eval do
|
54
54
|
alias_method :origin_to_a, :to_a
|
55
|
+
|
55
56
|
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
56
57
|
# if select only one object, then the only one object has impossible to cause N+1 query.
|
57
58
|
def to_a
|
@@ -128,12 +129,17 @@ module Bullet
|
|
128
129
|
id = row[key]
|
129
130
|
next unless id.nil?
|
130
131
|
|
131
|
-
associations = node.reflection.name
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
132
|
+
associations = [node.reflection.name]
|
133
|
+
if node.reflection.nested?
|
134
|
+
associations << node.reflection.through_reflection.name
|
135
|
+
end
|
136
|
+
associations.each do |association|
|
137
|
+
Bullet::Detector::Association.add_object_associations(ar_parent, association)
|
138
|
+
Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
|
139
|
+
@bullet_eager_loadings[ar_parent.class] ||= {}
|
140
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
|
141
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] << association
|
142
|
+
end
|
137
143
|
end
|
138
144
|
end
|
139
145
|
end
|
@@ -146,12 +152,17 @@ module Bullet
|
|
146
152
|
result = origin_construct_model(record, node, row, model_cache, id, aliases)
|
147
153
|
|
148
154
|
if Bullet.start?
|
149
|
-
associations = node.reflection.name
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
+
associations = [node.reflection.name]
|
156
|
+
if node.reflection.nested?
|
157
|
+
associations << node.reflection.through_reflection.name
|
158
|
+
end
|
159
|
+
associations.each do |association|
|
160
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
161
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, association)
|
162
|
+
@bullet_eager_loadings[record.class] ||= {}
|
163
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
164
|
+
@bullet_eager_loadings[record.class][record] << association
|
165
|
+
end
|
155
166
|
end
|
156
167
|
|
157
168
|
result
|
@@ -232,6 +243,16 @@ module Bullet
|
|
232
243
|
origin_count_records
|
233
244
|
end
|
234
245
|
end
|
246
|
+
|
247
|
+
::ActiveRecord::Associations::CollectionProxy.class_eval do
|
248
|
+
def count(column_name = nil, options = {})
|
249
|
+
if Bullet.start?
|
250
|
+
Bullet::Detector::CounterCache.add_counter_cache(proxy_association.owner, proxy_association.reflection.name)
|
251
|
+
Bullet::Detector::NPlusOneQuery.call_association(proxy_association.owner, proxy_association.reflection.name)
|
252
|
+
end
|
253
|
+
super(column_name, options)
|
254
|
+
end
|
255
|
+
end
|
235
256
|
end
|
236
257
|
end
|
237
258
|
end
|
@@ -138,12 +138,17 @@ module Bullet
|
|
138
138
|
id = row[key]
|
139
139
|
next unless id.nil?
|
140
140
|
|
141
|
-
associations = node.reflection.name
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
141
|
+
associations = [node.reflection.name]
|
142
|
+
if node.reflection.through_reflection?
|
143
|
+
associations << node.reflection.through_reflection.name
|
144
|
+
end
|
145
|
+
associations.each do |association|
|
146
|
+
Bullet::Detector::Association.add_object_associations(ar_parent, association)
|
147
|
+
Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
|
148
|
+
@bullet_eager_loadings[ar_parent.class] ||= {}
|
149
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
|
150
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] << association
|
151
|
+
end
|
147
152
|
end
|
148
153
|
end
|
149
154
|
end
|
@@ -156,12 +161,17 @@ module Bullet
|
|
156
161
|
result = super
|
157
162
|
|
158
163
|
if Bullet.start?
|
159
|
-
associations = node.reflection.name
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
164
|
+
associations = [node.reflection.name]
|
165
|
+
if node.reflection.through_reflection?
|
166
|
+
associations << node.reflection.through_reflection.name
|
167
|
+
end
|
168
|
+
associations.each do |association|
|
169
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
170
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, association)
|
171
|
+
@bullet_eager_loadings[record.class] ||= {}
|
172
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
173
|
+
@bullet_eager_loadings[record.class][record] << association
|
174
|
+
end
|
165
175
|
end
|
166
176
|
|
167
177
|
result
|
@@ -177,16 +187,18 @@ module Bullet
|
|
177
187
|
if Bullet.start?
|
178
188
|
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
179
189
|
refl = reflection.through_reflection
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
190
|
+
association = owner.association(refl.name)
|
191
|
+
if association.loaded?
|
192
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
|
193
|
+
Array.wrap(association.target).each do |through_record|
|
194
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
195
|
+
end
|
185
196
|
|
186
|
-
|
187
|
-
|
197
|
+
if refl.through_reflection?
|
198
|
+
refl = refl.through_reflection while refl.through_reflection?
|
188
199
|
|
189
|
-
|
200
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
|
201
|
+
end
|
190
202
|
end
|
191
203
|
end
|
192
204
|
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
|
@@ -258,6 +270,24 @@ module Bullet
|
|
258
270
|
end
|
259
271
|
end
|
260
272
|
)
|
273
|
+
|
274
|
+
::ActiveRecord::Associations::CollectionProxy.prepend(
|
275
|
+
Module.new do
|
276
|
+
def count
|
277
|
+
if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
278
|
+
Bullet::Detector::CounterCache.add_counter_cache(
|
279
|
+
proxy_association.owner,
|
280
|
+
proxy_association.reflection.name
|
281
|
+
)
|
282
|
+
Bullet::Detector::NPlusOneQuery.call_association(
|
283
|
+
proxy_association.owner,
|
284
|
+
proxy_association.reflection.name
|
285
|
+
)
|
286
|
+
end
|
287
|
+
super
|
288
|
+
end
|
289
|
+
end
|
290
|
+
)
|
261
291
|
end
|
262
292
|
end
|
263
293
|
end
|