bullet 5.5.0 → 5.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -5
- data/CHANGELOG.md +31 -1
- data/Gemfile +6 -1
- data/Gemfile.rails-5.0 +1 -1
- data/Gemfile.rails-5.1 +15 -0
- data/Gemfile.rails-5.2 +15 -0
- data/Guardfile +2 -2
- data/Hacking.md +1 -1
- data/README.md +20 -23
- data/Rakefile +20 -21
- data/bullet.gemspec +20 -15
- data/lib/bullet/active_record4.rb +18 -14
- data/lib/bullet/active_record41.rb +16 -14
- data/lib/bullet/active_record42.rb +24 -22
- data/lib/bullet/active_record5.rb +102 -91
- data/lib/bullet/active_record52.rb +232 -0
- data/lib/bullet/dependency.rb +9 -1
- data/lib/bullet/detector/association.rb +17 -14
- data/lib/bullet/detector/base.rb +2 -0
- data/lib/bullet/detector/counter_cache.rb +14 -10
- data/lib/bullet/detector/n_plus_one_query.rb +21 -17
- data/lib/bullet/detector/unused_eager_loading.rb +30 -24
- data/lib/bullet/detector.rb +2 -0
- data/lib/bullet/ext/object.rb +6 -4
- data/lib/bullet/ext/string.rb +3 -1
- data/lib/bullet/mongoid4x.rb +7 -2
- data/lib/bullet/mongoid5x.rb +7 -2
- data/lib/bullet/mongoid6x.rb +11 -6
- data/lib/bullet/notification/base.rb +26 -19
- data/lib/bullet/notification/counter_cache.rb +3 -1
- data/lib/bullet/notification/n_plus_one_query.rb +7 -4
- data/lib/bullet/notification/unused_eager_loading.rb +7 -4
- data/lib/bullet/notification.rb +2 -0
- data/lib/bullet/notification_collector.rb +2 -1
- data/lib/bullet/rack.rb +22 -18
- data/lib/bullet/registry/association.rb +2 -0
- data/lib/bullet/registry/base.rb +2 -0
- data/lib/bullet/registry/object.rb +2 -0
- data/lib/bullet/registry.rb +2 -0
- data/lib/bullet/stack_trace_filter.rb +56 -18
- data/lib/bullet/version.rb +3 -2
- data/lib/bullet.rb +43 -33
- data/lib/generators/bullet/install_generator.rb +48 -0
- data/perf/benchmark.rb +12 -12
- data/rails/init.rb +2 -0
- data/spec/bullet/detector/association_spec.rb +6 -4
- data/spec/bullet/detector/base_spec.rb +2 -0
- data/spec/bullet/detector/counter_cache_spec.rb +13 -11
- data/spec/bullet/detector/n_plus_one_query_spec.rb +71 -46
- data/spec/bullet/detector/unused_eager_loading_spec.rb +21 -19
- data/spec/bullet/ext/object_spec.rb +10 -8
- data/spec/bullet/ext/string_spec.rb +7 -5
- data/spec/bullet/notification/base_spec.rb +39 -38
- data/spec/bullet/notification/counter_cache_spec.rb +5 -3
- data/spec/bullet/notification/n_plus_one_query_spec.rb +5 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +4 -2
- data/spec/bullet/notification_collector_spec.rb +12 -10
- data/spec/bullet/rack_spec.rb +48 -47
- data/spec/bullet/registry/association_spec.rb +12 -10
- data/spec/bullet/registry/base_spec.rb +22 -20
- data/spec/bullet/registry/object_spec.rb +6 -4
- data/spec/bullet_spec.rb +24 -3
- data/spec/integration/{active_record4 → active_record}/association_spec.rb +176 -114
- data/spec/integration/counter_cache_spec.rb +15 -13
- data/spec/integration/mongoid/association_spec.rb +35 -33
- data/spec/models/address.rb +2 -0
- data/spec/models/author.rb +2 -0
- data/spec/models/base_user.rb +2 -0
- data/spec/models/category.rb +2 -0
- data/spec/models/city.rb +2 -0
- data/spec/models/client.rb +4 -0
- data/spec/models/comment.rb +3 -1
- data/spec/models/company.rb +2 -0
- data/spec/models/country.rb +2 -0
- data/spec/models/document.rb +4 -2
- data/spec/models/entry.rb +2 -0
- data/spec/models/firm.rb +3 -0
- data/spec/models/folder.rb +2 -0
- data/spec/models/group.rb +4 -0
- data/spec/models/mongoid/address.rb +3 -1
- data/spec/models/mongoid/category.rb +4 -2
- data/spec/models/mongoid/comment.rb +3 -1
- data/spec/models/mongoid/company.rb +3 -1
- data/spec/models/mongoid/entry.rb +3 -1
- data/spec/models/mongoid/post.rb +6 -4
- data/spec/models/mongoid/user.rb +2 -0
- data/spec/models/newspaper.rb +3 -1
- data/spec/models/page.rb +2 -0
- data/spec/models/person.rb +2 -0
- data/spec/models/pet.rb +2 -0
- data/spec/models/post.rb +17 -0
- data/spec/models/relationship.rb +2 -0
- data/spec/models/reply.rb +2 -0
- data/spec/models/student.rb +2 -0
- data/spec/models/submission.rb +2 -0
- data/spec/models/teacher.rb +2 -0
- data/spec/models/user.rb +2 -0
- data/spec/models/writer.rb +2 -0
- data/spec/spec_helper.rb +15 -13
- data/spec/support/bullet_ext.rb +2 -0
- data/spec/support/mongo_seed.rb +36 -42
- data/spec/support/rack_double.rb +13 -19
- data/spec/support/sqlite_seed.rb +84 -76
- data/tasks/bullet_tasks.rake +4 -2
- data/test.sh +2 -0
- data/update.sh +2 -0
- metadata +17 -11
- data/spec/integration/active_record5/association_spec.rb +0 -768
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0b65855ae5365567a18d1fb6ffdee5046b8cec35
|
|
4
|
+
data.tar.gz: 8df6b7afd18400dd2fe9bf39ec4a537fa04228af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 212cf02f1520dfaf752f794e42e9b2611fa0eca8b786bf5ef281c36c416ddf24016a524029614447c6241ebb734a2491ab554fa505544d7a7bc6f2e5b767527d
|
|
7
|
+
data.tar.gz: d2d71ceb54033f58cb6d675ea88268f130a0ea8bcfd7b4987486e374a2d2a3fc9169691ff20a9ca0fd9cf2787656dacc19649a8473879e9d1d68484597ccc18b
|
data/.travis.yml
CHANGED
|
@@ -3,14 +3,10 @@ language: ruby
|
|
|
3
3
|
rvm:
|
|
4
4
|
- 2.3.0
|
|
5
5
|
gemfile:
|
|
6
|
+
- Gemfile.rails-5.1
|
|
6
7
|
- Gemfile.rails-5.0
|
|
7
8
|
- Gemfile.rails-4.2
|
|
8
9
|
- Gemfile.rails-4.1
|
|
9
10
|
- Gemfile.rails-4.0
|
|
10
|
-
- Gemfile.mongoid-6.0
|
|
11
|
-
- Gemfile.mongoid-5.0
|
|
12
|
-
- Gemfile.mongoid-4.0
|
|
13
11
|
env:
|
|
14
12
|
- DB=sqlite
|
|
15
|
-
services:
|
|
16
|
-
- mongodb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
## Next Release
|
|
2
|
+
|
|
3
|
+
## 5.8.0 (10/29/2018)
|
|
4
|
+
|
|
5
|
+
* Fix through reflection for rails 5.x
|
|
6
|
+
* Fix false positive in after_save/after_create callbacks
|
|
7
|
+
* Don't triger a preload error on "manual" preloads
|
|
8
|
+
* Avoid Bullet from making extra queries in mongoid6
|
|
9
|
+
* Support option for #first and #last on mongoid6.x
|
|
10
|
+
* Fix duplicate logs in mongoid 4.x and 5.x version
|
|
11
|
+
* Use caller for ruby 1.9 while caller_locations for 2.0+
|
|
12
|
+
* Extend stacktrace matching for sub-file precision
|
|
13
|
+
* Exclude configured bundler path in addition to '/vendor'
|
|
14
|
+
* Fix `caller_path` in `excluded_stacktrace_path`
|
|
15
|
+
* Update `uniform_notifier` dependency to add Sentry support
|
|
16
|
+
* Integrate awesomecode.io and refactor code
|
|
17
|
+
|
|
18
|
+
## 5.7.0 (12/03/2017)
|
|
19
|
+
|
|
20
|
+
* Support rails 5.2
|
|
21
|
+
* Implement Bullet.delete_whitelist to delete a specific whitelist definition
|
|
22
|
+
* Fix caller_path in the case of nil
|
|
23
|
+
|
|
24
|
+
## 5.6.0 (07/16/2017)
|
|
25
|
+
|
|
26
|
+
* Migrate alias_method to Module#prepend
|
|
27
|
+
* Add install generator
|
|
28
|
+
* Stack trace filter
|
|
29
|
+
* Fix rails 5.1 compatibility
|
|
30
|
+
* Fix inverse_of for rails 5
|
|
31
|
+
* Fix detect file attachment for rack #319
|
|
2
32
|
|
|
3
33
|
## 5.5.0 (12/30/2016)
|
|
4
34
|
|
data/Gemfile
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
+
git_source(:github) do |repo_name|
|
|
4
|
+
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/')
|
|
5
|
+
"https://github.com/#{repo_name}.git"
|
|
6
|
+
end
|
|
7
|
+
|
|
3
8
|
gemspec
|
|
4
9
|
|
|
5
|
-
gem 'rails', github: 'rails
|
|
10
|
+
gem 'rails', github: 'rails'
|
|
6
11
|
gem 'sqlite3', platforms: [:ruby]
|
|
7
12
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
13
|
gem 'activerecord-import'
|
data/Gemfile.rails-5.0
CHANGED
data/Gemfile.rails-5.1
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
gem 'rails', '~> 5.1.0'
|
|
6
|
+
gem 'sqlite3'
|
|
7
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
+
gem 'activerecord-import'
|
|
9
|
+
|
|
10
|
+
gem "rspec"
|
|
11
|
+
|
|
12
|
+
platforms :rbx do
|
|
13
|
+
gem 'rubysl', '~> 2.0'
|
|
14
|
+
gem 'rubinius-developer_tools'
|
|
15
|
+
end
|
data/Gemfile.rails-5.2
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
gem 'rails', '~> 5.2.0'
|
|
6
|
+
gem 'sqlite3'
|
|
7
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
+
gem 'activerecord-import'
|
|
9
|
+
|
|
10
|
+
gem "rspec"
|
|
11
|
+
|
|
12
|
+
platforms :rbx do
|
|
13
|
+
gem 'rubysl', '~> 2.0'
|
|
14
|
+
gem 'rubinius-developer_tools'
|
|
15
|
+
end
|
data/Guardfile
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# A sample Guardfile
|
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
|
3
3
|
|
|
4
|
-
guard 'rspec', :
|
|
4
|
+
guard 'rspec', version: 2, all_after_pass: false, all_on_start: false, cli: '--color --format nested --fail-fast' do
|
|
5
5
|
watch(%r{^spec/.+_spec\.rb$})
|
|
6
6
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
7
|
-
watch('spec/spec_helper.rb') {
|
|
7
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
|
8
8
|
end
|
data/Hacking.md
CHANGED
|
@@ -28,7 +28,7 @@ So the flow of a request goes like this:
|
|
|
28
28
|
the notification collector
|
|
29
29
|
2. The request is handled by Rails, and the installed ActiveRecord extensions
|
|
30
30
|
trigger Detector callbacks
|
|
31
|
-
3. Detectors once called, will determine whether something noteworthy
|
|
31
|
+
3. Detectors once called, will determine whether something noteworthy happened.
|
|
32
32
|
If yes, then a Notification is created and stored in the notification collector.
|
|
33
33
|
4. Rails finishes handling the request
|
|
34
34
|
5. For each notification in the collector, Bullet will iterate over each
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](http://badge.fury.io/rb/bullet)
|
|
4
4
|
[](http://travis-ci.org/flyerhzm/bullet)
|
|
5
|
-
|
|
5
|
+
[](https://awesomecode.io/repos/flyerhzm/bullet)
|
|
6
6
|
[](http://coderwall.com/flyerhzm)
|
|
7
7
|
|
|
8
8
|
The Bullet gem is designed to help you increase your application's performance by reducing the number of queries it makes. It will watch your queries while you develop your application and notify you when you should add eager loading (N+1 queries), when you're using eager loading that isn't necessary and when you should use counter cache.
|
|
@@ -13,7 +13,7 @@ Bullet gem now supports **activerecord** >= 4.0 and **mongoid** >= 4.0.
|
|
|
13
13
|
|
|
14
14
|
If you use activerecord 2.x, please use bullet <= 4.5.0
|
|
15
15
|
|
|
16
|
-
If you use activerecord 3.x,
|
|
16
|
+
If you use activerecord 3.x, please use bullet < 5.5.0
|
|
17
17
|
|
|
18
18
|
## External Introduction
|
|
19
19
|
|
|
@@ -34,7 +34,7 @@ or add it into a Gemfile (Bundler):
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
```ruby
|
|
37
|
-
gem
|
|
37
|
+
gem 'bullet', group: 'development'
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
**Note**: make sure `bullet` gem is added after activerecord (rails) and
|
|
@@ -48,6 +48,7 @@ Bullet won't do ANYTHING unless you tell it to explicitly. Append to
|
|
|
48
48
|
```ruby
|
|
49
49
|
config.after_initialize do
|
|
50
50
|
Bullet.enable = true
|
|
51
|
+
Bullet.sentry = true
|
|
51
52
|
Bullet.alert = true
|
|
52
53
|
Bullet.bullet_logger = true
|
|
53
54
|
Bullet.console = true
|
|
@@ -63,30 +64,34 @@ config.after_initialize do
|
|
|
63
64
|
Bullet.rollbar = true
|
|
64
65
|
Bullet.add_footer = true
|
|
65
66
|
Bullet.stacktrace_includes = [ 'your_gem', 'your_middleware' ]
|
|
66
|
-
Bullet.stacktrace_excludes = [ 'their_gem', 'their_middleware' ]
|
|
67
|
+
Bullet.stacktrace_excludes = [ 'their_gem', 'their_middleware', ['my_file.rb', 'my_method'], ['my_file.rb', 16..20] ]
|
|
67
68
|
Bullet.slack = { webhook_url: 'http://some.slack.url', channel: '#default', username: 'notifier' }
|
|
68
69
|
end
|
|
69
70
|
```
|
|
70
71
|
|
|
71
72
|
The notifier of Bullet is a wrap of [uniform_notifier](https://github.com/flyerhzm/uniform_notifier)
|
|
72
73
|
|
|
73
|
-
The code above will enable all
|
|
74
|
+
The code above will enable all of the Bullet notification systems:
|
|
74
75
|
* `Bullet.enable`: enable Bullet gem, otherwise do nothing
|
|
75
76
|
* `Bullet.alert`: pop up a JavaScript alert in the browser
|
|
76
77
|
* `Bullet.bullet_logger`: log to the Bullet log file (Rails.root/log/bullet.log)
|
|
78
|
+
* `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
|
|
79
|
+
* `Bullet.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
|
|
80
|
+
* `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.
|
|
77
81
|
* `Bullet.rails_logger`: add warnings directly to the Rails log
|
|
78
82
|
* `Bullet.honeybadger`: add notifications to Honeybadger
|
|
79
83
|
* `Bullet.bugsnag`: add notifications to bugsnag
|
|
80
84
|
* `Bullet.airbrake`: add notifications to airbrake
|
|
81
85
|
* `Bullet.rollbar`: add notifications to rollbar
|
|
82
|
-
* `Bullet.
|
|
83
|
-
* `Bullet.growl`: pop up Growl warnings if your system has Growl installed. Requires a little bit of configuration
|
|
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.
|
|
85
|
-
* `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
|
|
86
|
+
* `Bullet.sentry`: add notifications to sentry
|
|
86
87
|
* `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.
|
|
87
88
|
* `Bullet.stacktrace_includes`: include paths with any of these substrings in the stack trace, even if they are not in your main app
|
|
88
89
|
* `Bullet.stacktrace_excludes`: ignore paths with any of these substrings in the stack trace, even if they are not in your main app.
|
|
90
|
+
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
|
|
91
|
+
item is a line number, a Range of line numbers, or a (bare) method name, to exclude only particular lines in a file.
|
|
89
92
|
* `Bullet.slack`: add notifications to slack
|
|
93
|
+
* `Bullet.raise`: raise errors, useful for making your specs fail unless they have optimized queries
|
|
94
|
+
|
|
90
95
|
|
|
91
96
|
Bullet also allows you to disable any of its detectors.
|
|
92
97
|
|
|
@@ -123,10 +128,11 @@ class ApplicationController < ActionController::Base
|
|
|
123
128
|
around_action :skip_bullet
|
|
124
129
|
|
|
125
130
|
def skip_bullet
|
|
131
|
+
previous_value = Bullet.enable?
|
|
126
132
|
Bullet.enable = false
|
|
127
133
|
yield
|
|
128
134
|
ensure
|
|
129
|
-
Bullet.enable =
|
|
135
|
+
Bullet.enable = previous_value
|
|
130
136
|
end
|
|
131
137
|
end
|
|
132
138
|
```
|
|
@@ -177,7 +183,7 @@ If you find Bullet does not work for you, *please disable your browser's cache*.
|
|
|
177
183
|
|
|
178
184
|
### Profile a job
|
|
179
185
|
|
|
180
|
-
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 use
|
|
186
|
+
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 use the profile method and fetch warnings
|
|
181
187
|
|
|
182
188
|
```ruby
|
|
183
189
|
Bullet.profile do
|
|
@@ -302,19 +308,10 @@ And run
|
|
|
302
308
|
bundle install
|
|
303
309
|
```
|
|
304
310
|
|
|
305
|
-
6\. enable the Bullet gem
|
|
306
|
-
`config/environments/development.rb`
|
|
311
|
+
6\. enable the Bullet gem with generate command
|
|
307
312
|
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
Bullet.enable = true
|
|
311
|
-
Bullet.alert = true
|
|
312
|
-
Bullet.bullet_logger = true
|
|
313
|
-
Bullet.console = true
|
|
314
|
-
# Bullet.growl = true
|
|
315
|
-
Bullet.rails_logger = true
|
|
316
|
-
Bullet.add_footer = true
|
|
317
|
-
end
|
|
313
|
+
```
|
|
314
|
+
bundle exec rails g bullet:install
|
|
318
315
|
```
|
|
319
316
|
|
|
320
317
|
7\. Start the server
|
data/Rakefile
CHANGED
|
@@ -1,52 +1,51 @@
|
|
|
1
|
-
$LOAD_PATH.unshift File.expand_path(
|
|
2
|
-
require
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
2
|
+
require 'bundler'
|
|
3
3
|
Bundler.setup
|
|
4
4
|
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
5
|
+
require 'rake'
|
|
6
|
+
require 'rspec'
|
|
7
|
+
require 'rspec/core/rake_task'
|
|
8
8
|
|
|
9
|
-
require
|
|
9
|
+
require 'bullet/version'
|
|
10
10
|
|
|
11
11
|
task :build do
|
|
12
|
-
system
|
|
12
|
+
system 'gem build bullet.gemspec'
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
task :
|
|
15
|
+
task install: :build do
|
|
16
16
|
system "sudo gem install bullet-#{Bullet::VERSION}.gem"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
task :
|
|
19
|
+
task release: :build do
|
|
20
20
|
puts "Tagging #{Bullet::VERSION}..."
|
|
21
21
|
system "git tag -a #{Bullet::VERSION} -m 'Tagging #{Bullet::VERSION}'"
|
|
22
|
-
puts
|
|
23
|
-
system
|
|
24
|
-
puts
|
|
22
|
+
puts 'Pushing to Github...'
|
|
23
|
+
system 'git push --tags'
|
|
24
|
+
puts 'Pushing to rubygems.org...'
|
|
25
25
|
system "gem push bullet-#{Bullet::VERSION}.gem"
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
29
|
-
spec.pattern =
|
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
RSpec::Core::RakeTask.new('spec:progress') do |spec|
|
|
33
|
-
spec.rspec_opts = %w
|
|
34
|
-
spec.pattern =
|
|
33
|
+
spec.rspec_opts = %w[--format progress]
|
|
34
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
|
|
38
37
|
begin
|
|
39
38
|
require 'rdoc/task'
|
|
40
39
|
|
|
41
|
-
desc
|
|
40
|
+
desc 'Generate documentation for the plugin.'
|
|
42
41
|
Rake::RDocTask.new do |rdoc|
|
|
43
|
-
rdoc.rdoc_dir =
|
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
44
43
|
rdoc.title = "bullet #{Bullet::VERSION}"
|
|
45
|
-
rdoc.rdoc_files.include(
|
|
46
|
-
rdoc.rdoc_files.include(
|
|
44
|
+
rdoc.rdoc_files.include('README*')
|
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
47
46
|
end
|
|
48
47
|
rescue LoadError
|
|
49
48
|
puts 'RDocTask is not supported for this platform'
|
|
50
49
|
end
|
|
51
50
|
|
|
52
|
-
task :
|
|
51
|
+
task default: :spec
|
data/bullet.gemspec
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
$:.unshift lib unless $:.include?(lib)
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
4
|
+
$LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
|
|
5
|
+
|
|
6
|
+
require 'bullet/version'
|
|
5
7
|
|
|
6
8
|
Gem::Specification.new do |s|
|
|
7
|
-
s.name =
|
|
9
|
+
s.name = 'bullet'
|
|
8
10
|
s.version = Bullet::VERSION
|
|
9
11
|
s.platform = Gem::Platform::RUBY
|
|
10
|
-
s.authors = [
|
|
11
|
-
s.email = [
|
|
12
|
-
s.homepage =
|
|
13
|
-
s.summary =
|
|
14
|
-
s.description =
|
|
12
|
+
s.authors = ['Richard Huang']
|
|
13
|
+
s.email = ['flyerhzm@gmail.com']
|
|
14
|
+
s.homepage = 'https://github.com/flyerhzm/bullet'
|
|
15
|
+
s.summary = 'help to kill N+1 queries and unused eager loading.'
|
|
16
|
+
s.description = 'help to kill N+1 queries and unused eager loading.'
|
|
17
|
+
s.metadata = {
|
|
18
|
+
'changelog_uri' => 'https://github.com/flyerhzm/bullet/blob/master/CHANGELOG.md',
|
|
19
|
+
'source_code_uri' => 'https://github.com/flyerhzm/bullet'
|
|
20
|
+
}
|
|
15
21
|
|
|
16
|
-
s.license
|
|
22
|
+
s.license = 'MIT'
|
|
17
23
|
|
|
18
|
-
s.required_rubygems_version =
|
|
24
|
+
s.required_rubygems_version = '>= 1.3.6'
|
|
19
25
|
|
|
20
|
-
s.add_runtime_dependency
|
|
21
|
-
s.add_runtime_dependency
|
|
26
|
+
s.add_runtime_dependency 'activesupport', '>= 3.0.0'
|
|
27
|
+
s.add_runtime_dependency 'uniform_notifier', '~> 1.11'
|
|
22
28
|
|
|
23
29
|
s.files = `git ls-files`.split("\n")
|
|
24
30
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
25
|
-
s.require_paths = [
|
|
31
|
+
s.require_paths = ['lib']
|
|
26
32
|
end
|
|
27
|
-
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Bullet
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
def self.enable
|
|
@@ -46,21 +48,12 @@ module Bullet
|
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
::ActiveRecord::Persistence.class_eval do
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
|
|
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
|
|
51
|
+
def _create_record_with_bullet(*args)
|
|
52
|
+
_create_record_without_bullet(*args).tap do
|
|
53
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
|
61
54
|
end
|
|
62
55
|
end
|
|
63
|
-
alias_method_chain :
|
|
56
|
+
alias_method_chain :_create_record, :bullet
|
|
64
57
|
end
|
|
65
58
|
|
|
66
59
|
::ActiveRecord::Associations::Preloader.class_eval do
|
|
@@ -72,6 +65,7 @@ module Bullet
|
|
|
72
65
|
if Bullet.start?
|
|
73
66
|
records = [records].flatten.compact.uniq
|
|
74
67
|
return if records.empty?
|
|
68
|
+
|
|
75
69
|
records.each do |record|
|
|
76
70
|
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
77
71
|
end
|
|
@@ -105,7 +99,7 @@ module Bullet
|
|
|
105
99
|
records = origin_instantiate(rows)
|
|
106
100
|
|
|
107
101
|
if Bullet.start?
|
|
108
|
-
@bullet_eager_loadings.each do |
|
|
102
|
+
@bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
|
|
109
103
|
objects = eager_loadings_hash.keys
|
|
110
104
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
111
105
|
end
|
|
@@ -187,6 +181,7 @@ module Bullet
|
|
|
187
181
|
::ActiveRecord::Associations::HasManyAssociation.class_eval do
|
|
188
182
|
alias_method :origin_has_cached_counter?, :has_cached_counter?
|
|
189
183
|
|
|
184
|
+
# rubocop:disable Style/MethodCallWithoutArgsParentheses
|
|
190
185
|
def has_cached_counter?(reflection = reflection())
|
|
191
186
|
result = origin_has_cached_counter?(reflection)
|
|
192
187
|
if Bullet.start? && !result
|
|
@@ -194,6 +189,15 @@ module Bullet
|
|
|
194
189
|
end
|
|
195
190
|
result
|
|
196
191
|
end
|
|
192
|
+
# rubocop:enable Style/MethodCallWithoutArgsParentheses
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
::ActiveRecord::Associations::BelongsToAssociation.class_eval do
|
|
196
|
+
def writer_with_bullet(record)
|
|
197
|
+
Bullet::Detector::Association.add_object_associations(owner, reflection.name) if Bullet.start?
|
|
198
|
+
writer_without_bullet(record)
|
|
199
|
+
end
|
|
200
|
+
alias_method_chain :writer, :bullet
|
|
197
201
|
end
|
|
198
202
|
end
|
|
199
203
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Bullet
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
def self.enable
|
|
@@ -48,21 +50,12 @@ module Bullet
|
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
::ActiveRecord::Persistence.class_eval do
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
alias_method_chain :save, :bullet
|
|
58
|
-
|
|
59
|
-
def save_with_bullet!(*args, &proc)
|
|
60
|
-
was_new_record = new_record?
|
|
61
|
-
save_without_bullet!(*args, &proc).tap do |result|
|
|
62
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
53
|
+
def _create_record_with_bullet(*args)
|
|
54
|
+
_create_record_without_bullet(*args).tap do
|
|
55
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
|
63
56
|
end
|
|
64
57
|
end
|
|
65
|
-
alias_method_chain :
|
|
58
|
+
alias_method_chain :_create_record, :bullet
|
|
66
59
|
end
|
|
67
60
|
|
|
68
61
|
::ActiveRecord::Associations::Preloader.class_eval do
|
|
@@ -87,6 +80,7 @@ module Bullet
|
|
|
87
80
|
alias_method :origin_find_with_associations, :find_with_associations
|
|
88
81
|
def find_with_associations
|
|
89
82
|
return origin_find_with_associations { |r| yield r } if block_given?
|
|
83
|
+
|
|
90
84
|
records = origin_find_with_associations
|
|
91
85
|
if Bullet.start?
|
|
92
86
|
associations = (eager_load_values + includes_values).uniq
|
|
@@ -108,7 +102,7 @@ module Bullet
|
|
|
108
102
|
records = origin_instantiate(result_set, aliases)
|
|
109
103
|
|
|
110
104
|
if Bullet.start?
|
|
111
|
-
@bullet_eager_loadings.each do |
|
|
105
|
+
@bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
|
|
112
106
|
objects = eager_loadings_hash.keys
|
|
113
107
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
114
108
|
end
|
|
@@ -185,6 +179,14 @@ module Bullet
|
|
|
185
179
|
origin_count_records
|
|
186
180
|
end
|
|
187
181
|
end
|
|
182
|
+
|
|
183
|
+
::ActiveRecord::Associations::BelongsToAssociation.class_eval do
|
|
184
|
+
def writer_with_bullet(record)
|
|
185
|
+
Bullet::Detector::Association.add_object_associations(owner, reflection.name) if Bullet.start?
|
|
186
|
+
writer_without_bullet(record)
|
|
187
|
+
end
|
|
188
|
+
alias_method_chain :writer, :bullet
|
|
189
|
+
end
|
|
188
190
|
end
|
|
189
191
|
end
|
|
190
192
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Bullet
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
def self.enable
|
|
@@ -42,21 +44,12 @@ module Bullet
|
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
::ActiveRecord::Persistence.class_eval do
|
|
45
|
-
def
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
47
|
+
def _create_record_with_bullet(*args)
|
|
48
|
+
_create_record_without_bullet(*args).tap do
|
|
49
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
|
49
50
|
end
|
|
50
51
|
end
|
|
51
|
-
alias_method_chain :
|
|
52
|
-
|
|
53
|
-
def save_with_bullet!(*args, &proc)
|
|
54
|
-
was_new_record = new_record?
|
|
55
|
-
save_without_bullet!(*args, &proc).tap do |result|
|
|
56
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
alias_method_chain :save!, :bullet
|
|
52
|
+
alias_method_chain :_create_record, :bullet
|
|
60
53
|
end
|
|
61
54
|
|
|
62
55
|
::ActiveRecord::Relation.class_eval do
|
|
@@ -102,6 +95,7 @@ module Bullet
|
|
|
102
95
|
alias_method :origin_find_with_associations, :find_with_associations
|
|
103
96
|
def find_with_associations
|
|
104
97
|
return origin_find_with_associations { |r| yield r } if block_given?
|
|
98
|
+
|
|
105
99
|
records = origin_find_with_associations
|
|
106
100
|
if Bullet.start?
|
|
107
101
|
associations = (eager_load_values + includes_values).uniq
|
|
@@ -124,7 +118,7 @@ module Bullet
|
|
|
124
118
|
records = origin_instantiate(result_set, aliases)
|
|
125
119
|
|
|
126
120
|
if Bullet.start?
|
|
127
|
-
@bullet_eager_loadings.each do |
|
|
121
|
+
@bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
|
|
128
122
|
objects = eager_loadings_hash.keys
|
|
129
123
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
130
124
|
end
|
|
@@ -138,14 +132,14 @@ module Bullet
|
|
|
138
132
|
parent.children.each do |node|
|
|
139
133
|
key = aliases.column_alias(node, node.primary_key)
|
|
140
134
|
id = row[key]
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
135
|
+
next unless id.nil?
|
|
136
|
+
|
|
137
|
+
associations = node.reflection.name
|
|
138
|
+
Bullet::Detector::Association.add_object_associations(ar_parent, associations)
|
|
139
|
+
Bullet::Detector::NPlusOneQuery.call_association(ar_parent, associations)
|
|
140
|
+
@bullet_eager_loadings[ar_parent.class] ||= {}
|
|
141
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
|
|
142
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] << associations
|
|
149
143
|
end
|
|
150
144
|
end
|
|
151
145
|
end
|
|
@@ -246,6 +240,14 @@ module Bullet
|
|
|
246
240
|
origin_count_records
|
|
247
241
|
end
|
|
248
242
|
end
|
|
243
|
+
|
|
244
|
+
::ActiveRecord::Associations::BelongsToAssociation.class_eval do
|
|
245
|
+
def writer_with_bullet(record)
|
|
246
|
+
Bullet::Detector::Association.add_object_associations(owner, reflection.name) if Bullet.start?
|
|
247
|
+
writer_without_bullet(record)
|
|
248
|
+
end
|
|
249
|
+
alias_method_chain :writer, :bullet
|
|
250
|
+
end
|
|
249
251
|
end
|
|
250
252
|
end
|
|
251
253
|
end
|