bullet 6.0.2 → 6.1.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 +3 -1
- data/CHANGELOG.md +7 -0
- data/README.md +4 -2
- data/lib/bullet.rb +25 -16
- data/lib/bullet/active_job.rb +1 -7
- data/lib/bullet/active_record4.rb +9 -23
- data/lib/bullet/active_record41.rb +7 -19
- data/lib/bullet/active_record42.rb +8 -16
- data/lib/bullet/active_record5.rb +188 -170
- data/lib/bullet/active_record52.rb +176 -161
- data/lib/bullet/active_record60.rb +183 -175
- data/lib/bullet/bullet_xhr.js +3 -9
- data/lib/bullet/dependency.rb +36 -34
- data/lib/bullet/detector/association.rb +24 -18
- data/lib/bullet/detector/base.rb +1 -2
- data/lib/bullet/detector/counter_cache.rb +10 -6
- data/lib/bullet/detector/n_plus_one_query.rb +18 -8
- data/lib/bullet/detector/unused_eager_loading.rb +5 -2
- data/lib/bullet/mongoid4x.rb +2 -6
- data/lib/bullet/mongoid5x.rb +2 -6
- data/lib/bullet/mongoid6x.rb +2 -6
- data/lib/bullet/mongoid7x.rb +2 -6
- data/lib/bullet/notification/base.rb +14 -18
- data/lib/bullet/notification/n_plus_one_query.rb +2 -4
- data/lib/bullet/notification/unused_eager_loading.rb +2 -4
- data/lib/bullet/rack.rb +5 -3
- data/lib/bullet/stack_trace_filter.rb +5 -10
- data/lib/bullet/version.rb +1 -1
- data/lib/generators/bullet/install_generator.rb +4 -2
- data/perf/benchmark.rb +8 -14
- data/spec/bullet/detector/counter_cache_spec.rb +5 -5
- data/spec/bullet/detector/n_plus_one_query_spec.rb +7 -3
- data/spec/bullet/detector/unused_eager_loading_spec.rb +29 -12
- data/spec/bullet/notification/base_spec.rb +1 -3
- data/spec/bullet/notification/n_plus_one_query_spec.rb +18 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +5 -1
- data/spec/bullet/rack_spec.rb +20 -5
- data/spec/bullet/registry/association_spec.rb +2 -2
- data/spec/bullet/registry/base_spec.rb +1 -1
- data/spec/bullet_spec.rb +10 -29
- data/spec/integration/active_record/association_spec.rb +42 -122
- data/spec/integration/counter_cache_spec.rb +10 -30
- data/spec/integration/mongoid/association_spec.rb +18 -32
- data/spec/models/folder.rb +1 -2
- data/spec/models/group.rb +1 -2
- data/spec/models/page.rb +1 -2
- data/spec/models/writer.rb +1 -2
- data/spec/spec_helper.rb +6 -10
- data/spec/support/bullet_ext.rb +8 -9
- data/spec/support/mongo_seed.rb +2 -16
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd668fdfd675ea8437eee0242974d7cb1cfacc0479be4cc5f3f58ee7d05a6d63
|
4
|
+
data.tar.gz: 3d841fb8471fe18b66135fa087ee3d1874f412c114d09ba05ba150e2daaf9775
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 714c614f2cf44f332f4f9996638c10dca565c92a2279316509256fefba2ca824fc9c71d2a3c3e4ca28edfc45849f76b61e521158e0051c365f5b8a81f41e9d8d
|
7
|
+
data.tar.gz: a3b1a7e58b6e5554a641aa4b8edf16dbb4983b2f7a072c5b7275ee04a7251e4d095fed37f82d2945ef759603c8aeaf8a394d9e7fcf9f70a723e6235ab5f3e646
|
data/.travis.yml
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
sudo: false
|
2
1
|
language: ruby
|
3
2
|
rvm:
|
4
3
|
- 2.3.0
|
@@ -29,3 +28,6 @@ matrix:
|
|
29
28
|
gemfile: Gemfile.rails-4.0
|
30
29
|
env:
|
31
30
|
- DB=sqlite
|
31
|
+
before_install:
|
32
|
+
- "find /home/travis/.rvm/rubies -wholename '*default/bundler-*.gemspec' -delete"
|
33
|
+
- gem install bundler -v '< 2'
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## Next Release
|
2
2
|
|
3
|
+
## 6.1.0 (12/28/2019)
|
4
|
+
|
5
|
+
* Add skip_html_injection flag
|
6
|
+
* Remove writer hack in active_record6
|
7
|
+
* Use modern includes syntax in warnings
|
8
|
+
* Fix warning: The last argument is used as the keyword parameter
|
9
|
+
|
3
10
|
## 6.0.2 (08/20/2019)
|
4
11
|
|
5
12
|
* Fully support Rails 6.0
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Bullet
|
2
2
|
|
3
|
-
[](http://badge.fury.io/rb/bullet)
|
4
|
+
[](http://travis-ci.org/flyerhzm/bullet)
|
5
5
|
[](https://awesomecode.io/repos/flyerhzm/bullet)
|
6
6
|
[](http://coderwall.com/flyerhzm)
|
7
7
|
|
@@ -63,6 +63,7 @@ config.after_initialize do
|
|
63
63
|
Bullet.airbrake = true
|
64
64
|
Bullet.rollbar = true
|
65
65
|
Bullet.add_footer = true
|
66
|
+
Bullet.skip_html_injection = false
|
66
67
|
Bullet.stacktrace_includes = [ 'your_gem', 'your_middleware' ]
|
67
68
|
Bullet.stacktrace_excludes = [ 'their_gem', 'their_middleware', ['my_file.rb', 'my_method'], ['my_file.rb', 16..20] ]
|
68
69
|
Bullet.slack = { webhook_url: 'http://some.slack.url', channel: '#default', username: 'notifier' }
|
@@ -85,6 +86,7 @@ The code above will enable all of the Bullet notification systems:
|
|
85
86
|
* `Bullet.rollbar`: add notifications to rollbar
|
86
87
|
* `Bullet.sentry`: add notifications to sentry
|
87
88
|
* `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 XHR into the returned HTML. This must be false for receiving alerts or console logging.
|
88
90
|
* `Bullet.stacktrace_includes`: include paths with any of these substrings in the stack trace, even if they are not in your main app
|
89
91
|
* `Bullet.stacktrace_excludes`: ignore paths with any of these substrings in the stack trace, even if they are not in your main app.
|
90
92
|
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
|
data/lib/bullet.rb
CHANGED
@@ -23,7 +23,7 @@ module Bullet
|
|
23
23
|
BULLET_DEBUG = 'BULLET_DEBUG'
|
24
24
|
TRUE = 'true'
|
25
25
|
|
26
|
-
if defined?
|
26
|
+
if defined?(Rails::Railtie)
|
27
27
|
class BulletRailtie < Rails::Railtie
|
28
28
|
initializer 'bullet.configure_rails_initialization' do |app|
|
29
29
|
app.middleware.use Bullet::Rack
|
@@ -32,28 +32,36 @@ module Bullet
|
|
32
32
|
end
|
33
33
|
|
34
34
|
class << self
|
35
|
-
attr_writer :n_plus_one_query_enable,
|
35
|
+
attr_writer :n_plus_one_query_enable,
|
36
|
+
:unused_eager_loading_enable,
|
37
|
+
:counter_cache_enable,
|
38
|
+
:stacktrace_includes,
|
39
|
+
:stacktrace_excludes,
|
40
|
+
:skip_html_injection
|
36
41
|
attr_reader :whitelist
|
37
|
-
attr_accessor :add_footer, :
|
42
|
+
attr_accessor :add_footer, :orm_patches_applied
|
38
43
|
|
39
44
|
available_notifiers = UniformNotifier::AVAILABLE_NOTIFIERS.map { |notifier| "#{notifier}=" }
|
40
|
-
|
41
|
-
delegate(*available_notifiers)
|
45
|
+
available_notifiers_options = { to: UniformNotifier }
|
46
|
+
delegate(*available_notifiers, **available_notifiers_options)
|
42
47
|
|
43
48
|
def raise=(should_raise)
|
44
49
|
UniformNotifier.raise = (should_raise ? Notification::UnoptimizedQueryError : false)
|
45
50
|
end
|
46
51
|
|
47
|
-
DETECTORS = [
|
48
|
-
|
49
|
-
|
52
|
+
DETECTORS = [
|
53
|
+
Bullet::Detector::NPlusOneQuery,
|
54
|
+
Bullet::Detector::UnusedEagerLoading,
|
55
|
+
Bullet::Detector::CounterCache
|
56
|
+
].freeze
|
50
57
|
|
51
58
|
def enable=(enable)
|
52
59
|
@enable = @n_plus_one_query_enable = @unused_eager_loading_enable = @counter_cache_enable = enable
|
60
|
+
|
53
61
|
if enable?
|
54
62
|
reset_whitelist
|
55
|
-
unless
|
56
|
-
self.
|
63
|
+
unless orm_patches_applied
|
64
|
+
self.orm_patches_applied = true
|
57
65
|
Bullet::Mongoid.enable if mongoid?
|
58
66
|
Bullet::ActiveRecord.enable if active_record?
|
59
67
|
end
|
@@ -174,9 +182,7 @@ module Bullet
|
|
174
182
|
|
175
183
|
def gather_inline_notifications
|
176
184
|
responses = []
|
177
|
-
for_each_active_notifier_with_notification
|
178
|
-
responses << notification.notify_inline
|
179
|
-
end
|
185
|
+
for_each_active_notifier_with_notification { |notification| responses << notification.notify_inline }
|
180
186
|
responses.join("\n")
|
181
187
|
end
|
182
188
|
|
@@ -190,9 +196,7 @@ module Bullet
|
|
190
196
|
|
191
197
|
def footer_info
|
192
198
|
info = []
|
193
|
-
notification_collector.collection.each
|
194
|
-
info << notification.short_notice
|
195
|
-
end
|
199
|
+
notification_collector.collection.each { |notification| info << notification.short_notice }
|
196
200
|
info
|
197
201
|
end
|
198
202
|
|
@@ -214,6 +218,7 @@ module Bullet
|
|
214
218
|
|
215
219
|
def profile
|
216
220
|
return_value = nil
|
221
|
+
|
217
222
|
if Bullet.enable?
|
218
223
|
begin
|
219
224
|
Bullet.start_request
|
@@ -235,6 +240,10 @@ module Bullet
|
|
235
240
|
UniformNotifier.active_notifiers.include?(UniformNotifier::JavascriptConsole)
|
236
241
|
end
|
237
242
|
|
243
|
+
def skip_html_injection?
|
244
|
+
@skip_html_injection || false
|
245
|
+
end
|
246
|
+
|
238
247
|
private
|
239
248
|
|
240
249
|
def for_each_active_notifier_with_notification
|
data/lib/bullet/active_job.rb
CHANGED
@@ -3,13 +3,7 @@
|
|
3
3
|
module Bullet
|
4
4
|
module ActiveJob
|
5
5
|
def self.included(base)
|
6
|
-
base.class_eval
|
7
|
-
around_perform do |_job, block|
|
8
|
-
Bullet.profile do
|
9
|
-
block.call
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
6
|
+
base.class_eval { around_perform { |_job, block| Bullet.profile { block.call } } }
|
13
7
|
end
|
14
8
|
end
|
15
9
|
end
|
@@ -5,7 +5,7 @@ module Bullet
|
|
5
5
|
def self.enable
|
6
6
|
require 'active_record'
|
7
7
|
::ActiveRecord::Base.class_eval do
|
8
|
-
class <<self
|
8
|
+
class << self
|
9
9
|
alias_method :origin_find_by_sql, :find_by_sql
|
10
10
|
def find_by_sql(sql, binds = [])
|
11
11
|
result = origin_find_by_sql(sql, binds)
|
@@ -49,9 +49,7 @@ module Bullet
|
|
49
49
|
|
50
50
|
::ActiveRecord::Persistence.class_eval do
|
51
51
|
def _create_record_with_bullet(*args)
|
52
|
-
_create_record_without_bullet(*args).tap
|
53
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
54
|
-
end
|
52
|
+
_create_record_without_bullet(*args).tap { Bullet::Detector::NPlusOneQuery.add_impossible_object(self) }
|
55
53
|
end
|
56
54
|
alias_method_chain :_create_record, :bullet
|
57
55
|
end
|
@@ -62,13 +60,12 @@ module Bullet
|
|
62
60
|
alias_method :origin_initialize, :initialize
|
63
61
|
def initialize(records, associations, preload_scope = nil)
|
64
62
|
origin_initialize(records, associations, preload_scope)
|
63
|
+
|
65
64
|
if Bullet.start?
|
66
65
|
records = [records].flatten.compact.uniq
|
67
66
|
return if records.empty?
|
68
67
|
|
69
|
-
records.each
|
70
|
-
Bullet::Detector::Association.add_object_associations(record, associations)
|
71
|
-
end
|
68
|
+
records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
|
72
69
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
73
70
|
end
|
74
71
|
end
|
@@ -81,9 +78,7 @@ module Bullet
|
|
81
78
|
records = origin_find_with_associations
|
82
79
|
if Bullet.start?
|
83
80
|
associations = (eager_load_values + includes_values).uniq
|
84
|
-
records.each
|
85
|
-
Bullet::Detector::Association.add_object_associations(record, associations)
|
86
|
-
end
|
81
|
+
records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
|
87
82
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
88
83
|
end
|
89
84
|
records
|
@@ -128,17 +123,13 @@ module Bullet
|
|
128
123
|
# call one to many associations
|
129
124
|
alias_method :origin_load_target, :load_target
|
130
125
|
def load_target
|
131
|
-
if Bullet.start?
|
132
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
133
|
-
end
|
126
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
|
134
127
|
origin_load_target
|
135
128
|
end
|
136
129
|
|
137
130
|
alias_method :origin_include?, :include?
|
138
131
|
def include?(object)
|
139
|
-
if Bullet.start?
|
140
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
141
|
-
end
|
132
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
|
142
133
|
origin_include?(object)
|
143
134
|
end
|
144
135
|
end
|
@@ -156,9 +147,7 @@ module Bullet
|
|
156
147
|
::ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
|
157
148
|
alias_method :origin_empty?, :empty?
|
158
149
|
def empty?
|
159
|
-
if Bullet.start? && !loaded?
|
160
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
161
|
-
end
|
150
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start? && !loaded?
|
162
151
|
origin_empty?
|
163
152
|
end
|
164
153
|
end
|
@@ -183,12 +172,9 @@ module Bullet
|
|
183
172
|
|
184
173
|
def has_cached_counter?(reflection = reflection())
|
185
174
|
result = origin_has_cached_counter?(reflection)
|
186
|
-
if Bullet.start? && !result
|
187
|
-
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
188
|
-
end
|
175
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name) if Bullet.start? && !result
|
189
176
|
result
|
190
177
|
end
|
191
|
-
|
192
178
|
end
|
193
179
|
end
|
194
180
|
end
|
@@ -5,7 +5,7 @@ module Bullet
|
|
5
5
|
def self.enable
|
6
6
|
require 'active_record'
|
7
7
|
::ActiveRecord::Base.class_eval do
|
8
|
-
class <<self
|
8
|
+
class << self
|
9
9
|
alias_method :origin_find_by_sql, :find_by_sql
|
10
10
|
def find_by_sql(sql, binds = [])
|
11
11
|
result = origin_find_by_sql(sql, binds)
|
@@ -51,9 +51,7 @@ module Bullet
|
|
51
51
|
|
52
52
|
::ActiveRecord::Persistence.class_eval do
|
53
53
|
def _create_record_with_bullet(*args)
|
54
|
-
_create_record_without_bullet(*args).tap
|
55
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
56
|
-
end
|
54
|
+
_create_record_without_bullet(*args).tap { Bullet::Detector::NPlusOneQuery.add_impossible_object(self) }
|
57
55
|
end
|
58
56
|
alias_method_chain :_create_record, :bullet
|
59
57
|
end
|
@@ -65,9 +63,7 @@ module Bullet
|
|
65
63
|
if Bullet.start?
|
66
64
|
records.compact!
|
67
65
|
if records.first.class.name !~ /^HABTM_/
|
68
|
-
records.each
|
69
|
-
Bullet::Detector::Association.add_object_associations(record, association)
|
70
|
-
end
|
66
|
+
records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
|
71
67
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
|
72
68
|
end
|
73
69
|
end
|
@@ -84,9 +80,7 @@ module Bullet
|
|
84
80
|
records = origin_find_with_associations
|
85
81
|
if Bullet.start?
|
86
82
|
associations = (eager_load_values + includes_values).uniq
|
87
|
-
records.each
|
88
|
-
Bullet::Detector::Association.add_object_associations(record, associations)
|
89
|
-
end
|
83
|
+
records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
|
90
84
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
91
85
|
end
|
92
86
|
records
|
@@ -131,9 +125,7 @@ module Bullet
|
|
131
125
|
# call one to many associations
|
132
126
|
alias_method :origin_load_target, :load_target
|
133
127
|
def load_target
|
134
|
-
if Bullet.start?
|
135
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless @inversed
|
136
|
-
end
|
128
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start? && !@inversed
|
137
129
|
origin_load_target
|
138
130
|
end
|
139
131
|
|
@@ -147,9 +139,7 @@ module Bullet
|
|
147
139
|
|
148
140
|
alias_method :origin_include?, :include?
|
149
141
|
def include?(object)
|
150
|
-
if Bullet.start?
|
151
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
152
|
-
end
|
142
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
|
153
143
|
origin_include?(object)
|
154
144
|
end
|
155
145
|
end
|
@@ -173,9 +163,7 @@ module Bullet
|
|
173
163
|
alias_method :origin_count_records, :count_records
|
174
164
|
def count_records
|
175
165
|
result = has_cached_counter?
|
176
|
-
if Bullet.start? && !result
|
177
|
-
Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name)
|
178
|
-
end
|
166
|
+
Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name) if Bullet.start? && !result
|
179
167
|
origin_count_records
|
180
168
|
end
|
181
169
|
end
|
@@ -5,7 +5,7 @@ module Bullet
|
|
5
5
|
def self.enable
|
6
6
|
require 'active_record'
|
7
7
|
::ActiveRecord::Base.class_eval do
|
8
|
-
class <<self
|
8
|
+
class << self
|
9
9
|
alias_method :origin_find, :find
|
10
10
|
def find(*args)
|
11
11
|
result = origin_find(*args)
|
@@ -45,9 +45,7 @@ module Bullet
|
|
45
45
|
|
46
46
|
::ActiveRecord::Persistence.class_eval do
|
47
47
|
def _create_record_with_bullet(*args)
|
48
|
-
_create_record_without_bullet(*args).tap
|
49
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
50
|
-
end
|
48
|
+
_create_record_without_bullet(*args).tap { Bullet::Detector::NPlusOneQuery.add_impossible_object(self) }
|
51
49
|
end
|
52
50
|
alias_method_chain :_create_record, :bullet
|
53
51
|
end
|
@@ -80,9 +78,7 @@ module Bullet
|
|
80
78
|
if Bullet.start?
|
81
79
|
records.compact!
|
82
80
|
if records.first.class.name !~ /^HABTM_/
|
83
|
-
records.each
|
84
|
-
Bullet::Detector::Association.add_object_associations(record, association)
|
85
|
-
end
|
81
|
+
records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
|
86
82
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
|
87
83
|
end
|
88
84
|
end
|
@@ -99,9 +95,7 @@ module Bullet
|
|
99
95
|
records = origin_find_with_associations
|
100
96
|
if Bullet.start?
|
101
97
|
associations = (eager_load_values + includes_values).uniq
|
102
|
-
records.each
|
103
|
-
Bullet::Detector::Association.add_object_associations(record, associations)
|
104
|
-
end
|
98
|
+
records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
|
105
99
|
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
106
100
|
end
|
107
101
|
records
|
@@ -195,9 +189,7 @@ module Bullet
|
|
195
189
|
|
196
190
|
alias_method :origin_include?, :include?
|
197
191
|
def include?(object)
|
198
|
-
if Bullet.start?
|
199
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
200
|
-
end
|
192
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) if Bullet.start?
|
201
193
|
origin_include?(object)
|
202
194
|
end
|
203
195
|
end
|
@@ -207,9 +199,11 @@ module Bullet
|
|
207
199
|
alias_method :origin_reader, :reader
|
208
200
|
def reader(force_reload = false)
|
209
201
|
result = origin_reader(force_reload)
|
202
|
+
|
210
203
|
if Bullet.start?
|
211
204
|
if @owner.class.name !~ /^HABTM_/ && !@inversed
|
212
205
|
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
206
|
+
|
213
207
|
if Bullet::Detector::NPlusOneQuery.impossible?(@owner)
|
214
208
|
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
215
209
|
else
|
@@ -234,9 +228,7 @@ module Bullet
|
|
234
228
|
alias_method :origin_count_records, :count_records
|
235
229
|
def count_records
|
236
230
|
result = has_cached_counter?
|
237
|
-
if Bullet.start? && !result
|
238
|
-
Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name)
|
239
|
-
end
|
231
|
+
Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name) if Bullet.start? && !result
|
240
232
|
origin_count_records
|
241
233
|
end
|
242
234
|
end
|
@@ -13,233 +13,251 @@ module Bullet
|
|
13
13
|
module ActiveRecord
|
14
14
|
def self.enable
|
15
15
|
require 'active_record'
|
16
|
-
::ActiveRecord::Base.extend(
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if
|
21
|
-
if result.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
::ActiveRecord::Base.extend(
|
17
|
+
Module.new do
|
18
|
+
def find_by_sql(sql, binds = [], preparable: nil, &block)
|
19
|
+
result = super
|
20
|
+
if Bullet.start?
|
21
|
+
if result.is_a? Array
|
22
|
+
if result.size > 1
|
23
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
24
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
25
|
+
elsif result.size == 1
|
26
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
27
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
28
|
+
end
|
29
|
+
elsif result.is_a? ::ActiveRecord::Base
|
30
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
|
31
|
+
Bullet::Detector::CounterCache.add_impossible_object(result)
|
27
32
|
end
|
28
|
-
elsif result.is_a? ::ActiveRecord::Base
|
29
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
|
30
|
-
Bullet::Detector::CounterCache.add_impossible_object(result)
|
31
33
|
end
|
34
|
+
result
|
32
35
|
end
|
33
|
-
result
|
34
36
|
end
|
35
|
-
|
37
|
+
)
|
36
38
|
|
37
39
|
::ActiveRecord::Base.prepend(SaveWithBulletSupport)
|
38
40
|
|
39
|
-
::ActiveRecord::Relation.prepend(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
if
|
46
|
-
if result.
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
41
|
+
::ActiveRecord::Relation.prepend(
|
42
|
+
Module.new do
|
43
|
+
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
44
|
+
# if select only one object, then the only one object has impossible to cause N+1 query.
|
45
|
+
def records
|
46
|
+
result = super
|
47
|
+
if Bullet.start?
|
48
|
+
if result.first.class.name !~ /^HABTM_/
|
49
|
+
if result.size > 1
|
50
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
51
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
52
|
+
elsif result.size == 1
|
53
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
54
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
55
|
+
end
|
52
56
|
end
|
53
57
|
end
|
58
|
+
result
|
54
59
|
end
|
55
|
-
result
|
56
60
|
end
|
57
|
-
|
58
|
-
|
59
|
-
::ActiveRecord::Associations::Preloader.prepend(
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
records.
|
65
|
-
Bullet::Detector::Association.add_object_associations(record, association)
|
61
|
+
)
|
62
|
+
|
63
|
+
::ActiveRecord::Associations::Preloader.prepend(
|
64
|
+
Module.new do
|
65
|
+
def preloaders_for_one(association, records, scope)
|
66
|
+
if Bullet.start?
|
67
|
+
records.compact!
|
68
|
+
if records.first.class.name !~ /^HABTM_/
|
69
|
+
records.each { |record| Bullet::Detector::Association.add_object_associations(record, association) }
|
70
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
|
66
71
|
end
|
67
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
|
68
72
|
end
|
73
|
+
super
|
69
74
|
end
|
70
|
-
super
|
71
75
|
end
|
72
|
-
|
76
|
+
)
|
73
77
|
|
74
|
-
::ActiveRecord::FinderMethods.prepend(
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
+
::ActiveRecord::FinderMethods.prepend(
|
79
|
+
Module.new do
|
80
|
+
# add includes in scope
|
81
|
+
def find_with_associations
|
82
|
+
return super { |r| yield r } if block_given?
|
78
83
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
Bullet::Detector::
|
84
|
+
records = super
|
85
|
+
if Bullet.start?
|
86
|
+
associations = (eager_load_values + includes_values).uniq
|
87
|
+
records.each { |record| Bullet::Detector::Association.add_object_associations(record, associations) }
|
88
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
84
89
|
end
|
85
|
-
|
90
|
+
records
|
86
91
|
end
|
87
|
-
records
|
88
92
|
end
|
89
|
-
|
93
|
+
)
|
90
94
|
|
91
|
-
::ActiveRecord::Associations::JoinDependency.prepend(
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
95
|
+
::ActiveRecord::Associations::JoinDependency.prepend(
|
96
|
+
Module.new do
|
97
|
+
if ::ActiveRecord::Associations::JoinDependency.instance_method(:instantiate).parameters.last[0] == :block
|
98
|
+
# ActiveRecord >= 5.1.5
|
99
|
+
def instantiate(result_set, &block)
|
100
|
+
@bullet_eager_loadings = {}
|
101
|
+
records = super
|
97
102
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
103
|
+
if Bullet.start?
|
104
|
+
@bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
|
105
|
+
objects = eager_loadings_hash.keys
|
106
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
|
107
|
+
objects,
|
108
|
+
eager_loadings_hash[objects.first].to_a
|
109
|
+
)
|
110
|
+
end
|
102
111
|
end
|
112
|
+
records
|
103
113
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
@bullet_eager_loadings = {}
|
110
|
-
records = super
|
114
|
+
else
|
115
|
+
# ActiveRecord <= 5.1.4
|
116
|
+
def instantiate(result_set, aliases)
|
117
|
+
@bullet_eager_loadings = {}
|
118
|
+
records = super
|
111
119
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
120
|
+
if Bullet.start?
|
121
|
+
@bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
|
122
|
+
objects = eager_loadings_hash.keys
|
123
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
|
124
|
+
objects,
|
125
|
+
eager_loadings_hash[objects.first].to_a
|
126
|
+
)
|
127
|
+
end
|
116
128
|
end
|
129
|
+
records
|
117
130
|
end
|
118
|
-
records
|
119
131
|
end
|
120
|
-
end
|
121
132
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
133
|
+
def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
|
134
|
+
if Bullet.start?
|
135
|
+
unless ar_parent.nil?
|
136
|
+
parent.children.each do |node|
|
137
|
+
key = aliases.column_alias(node, node.primary_key)
|
138
|
+
id = row[key]
|
139
|
+
next unless id.nil?
|
140
|
+
|
141
|
+
associations = node.reflection.name
|
142
|
+
Bullet::Detector::Association.add_object_associations(ar_parent, associations)
|
143
|
+
Bullet::Detector::NPlusOneQuery.call_association(ar_parent, associations)
|
144
|
+
@bullet_eager_loadings[ar_parent.class] ||= {}
|
145
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
|
146
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] << associations
|
147
|
+
end
|
136
148
|
end
|
137
149
|
end
|
150
|
+
|
151
|
+
super
|
138
152
|
end
|
139
153
|
|
140
|
-
|
141
|
-
|
154
|
+
# call join associations
|
155
|
+
def construct_model(record, node, row, model_cache, id, aliases)
|
156
|
+
result = super
|
142
157
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
@bullet_eager_loadings[record.class] ||= {}
|
152
|
-
@bullet_eager_loadings[record.class][record] ||= Set.new
|
153
|
-
@bullet_eager_loadings[record.class][record] << associations
|
154
|
-
end
|
158
|
+
if Bullet.start?
|
159
|
+
associations = node.reflection.name
|
160
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
161
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, associations)
|
162
|
+
@bullet_eager_loadings[record.class] ||= {}
|
163
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
164
|
+
@bullet_eager_loadings[record.class][record] << associations
|
165
|
+
end
|
155
166
|
|
156
|
-
|
167
|
+
result
|
168
|
+
end
|
157
169
|
end
|
158
|
-
|
159
|
-
|
160
|
-
::ActiveRecord::Associations::CollectionAssociation.prepend(Module.new do
|
161
|
-
def load_target
|
162
|
-
records = super
|
163
|
-
|
164
|
-
if Bullet.start?
|
165
|
-
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
166
|
-
refl = reflection.through_reflection
|
167
|
-
Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
|
168
|
-
association = owner.association refl.name
|
169
|
-
Array(association.target).each do |through_record|
|
170
|
-
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
171
|
-
end
|
170
|
+
)
|
172
171
|
|
173
|
-
|
174
|
-
|
172
|
+
::ActiveRecord::Associations::CollectionAssociation.prepend(
|
173
|
+
Module.new do
|
174
|
+
def load_target
|
175
|
+
records = super
|
175
176
|
|
177
|
+
if Bullet.start?
|
178
|
+
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
179
|
+
refl = reflection.through_reflection
|
176
180
|
Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
|
181
|
+
association = owner.association refl.name
|
182
|
+
Array(association.target).each do |through_record|
|
183
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
184
|
+
end
|
185
|
+
|
186
|
+
if refl.through_reflection?
|
187
|
+
refl = refl.through_reflection while refl.through_reflection?
|
188
|
+
|
189
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, refl.name)
|
190
|
+
end
|
177
191
|
end
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
192
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
|
193
|
+
if records.first.class.name !~ /^HABTM_/
|
194
|
+
if records.size > 1
|
195
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
196
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
197
|
+
elsif records.size == 1
|
198
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
199
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
200
|
+
end
|
187
201
|
end
|
188
202
|
end
|
203
|
+
records
|
189
204
|
end
|
190
|
-
records
|
191
|
-
end
|
192
205
|
|
193
|
-
|
194
|
-
|
195
|
-
|
206
|
+
def empty?
|
207
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
208
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
209
|
+
end
|
210
|
+
super
|
196
211
|
end
|
197
|
-
super
|
198
|
-
end
|
199
212
|
|
200
|
-
|
201
|
-
|
202
|
-
|
213
|
+
def include?(object)
|
214
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
|
215
|
+
super
|
203
216
|
end
|
204
|
-
super
|
205
217
|
end
|
206
|
-
|
207
|
-
|
208
|
-
::ActiveRecord::Associations::SingularAssociation.prepend(
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
if
|
216
|
-
Bullet::Detector::NPlusOneQuery.
|
217
|
-
|
218
|
-
Bullet::Detector::NPlusOneQuery.
|
218
|
+
)
|
219
|
+
|
220
|
+
::ActiveRecord::Associations::SingularAssociation.prepend(
|
221
|
+
Module.new do
|
222
|
+
# call has_one and belongs_to associations
|
223
|
+
def target
|
224
|
+
result = super()
|
225
|
+
|
226
|
+
if Bullet.start?
|
227
|
+
if owner.class.name !~ /^HABTM_/ && !@inversed
|
228
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
229
|
+
|
230
|
+
if Bullet::Detector::NPlusOneQuery.impossible?(owner)
|
231
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
232
|
+
else
|
233
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
|
234
|
+
end
|
219
235
|
end
|
220
236
|
end
|
237
|
+
result
|
221
238
|
end
|
222
|
-
result
|
223
239
|
end
|
224
|
-
|
240
|
+
)
|
225
241
|
|
226
|
-
::ActiveRecord::Associations::HasManyAssociation.prepend(
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
Bullet
|
242
|
+
::ActiveRecord::Associations::HasManyAssociation.prepend(
|
243
|
+
Module.new do
|
244
|
+
def empty?
|
245
|
+
result = super
|
246
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
247
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
248
|
+
end
|
249
|
+
result
|
231
250
|
end
|
232
|
-
result
|
233
|
-
end
|
234
251
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
252
|
+
def count_records
|
253
|
+
result = reflection.has_cached_counter?
|
254
|
+
if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
255
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
256
|
+
end
|
257
|
+
super
|
239
258
|
end
|
240
|
-
super
|
241
259
|
end
|
242
|
-
|
260
|
+
)
|
243
261
|
end
|
244
262
|
end
|
245
263
|
end
|