bullet 4.14.5 → 4.14.10
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 +2 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile.mongoid-5.0 +17 -0
- data/README.md +21 -0
- data/lib/bullet/active_record3.rb +65 -35
- data/lib/bullet/active_record3x.rb +54 -32
- data/lib/bullet/active_record4.rb +61 -31
- data/lib/bullet/active_record41.rb +62 -32
- data/lib/bullet/active_record42.rb +93 -49
- data/lib/bullet/dependency.rb +6 -0
- data/lib/bullet/detector/association.rb +16 -16
- data/lib/bullet/detector/counter_cache.rb +13 -13
- data/lib/bullet/detector/n_plus_one_query.rb +30 -30
- data/lib/bullet/detector/unused_eager_loading.rb +1 -1
- data/lib/bullet/ext/object.rb +3 -1
- data/lib/bullet/mongoid5x.rb +56 -0
- data/lib/bullet/rack.rb +2 -2
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +14 -4
- data/spec/bullet/detector/counter_cache_spec.rb +8 -8
- data/spec/bullet/detector/n_plus_one_query_spec.rb +27 -27
- data/spec/bullet/ext/object_spec.rb +6 -0
- data/spec/bullet/notification/base_spec.rb +2 -2
- data/spec/bullet_spec.rb +47 -0
- data/spec/integration/active_record3/association_spec.rb +11 -2
- data/spec/integration/active_record4/association_spec.rb +32 -2
- data/spec/integration/counter_cache_spec.rb +8 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/support/mongo_seed.rb +13 -0
- data/test.sh +1 -0
- data/update.sh +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 262911eb5bb5cc6577489084cca4c06042ec466b
|
|
4
|
+
data.tar.gz: 6aa0f9e1403c8f36cac9375b451880a82c9561cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 99c812cc4085c2e9763ba05564f98b4b3ab9027820932eb70d09060fbfb69071d38d8d844b67d29dc167ad04983e8133fa5727b426122d9a4e0f3b9c55e9bd3b
|
|
7
|
+
data.tar.gz: d1316bb72c9228fb4b7746795d528506eb472d1bd906424c17bbb5a3adcdd995e75bcdec59b8a93959d80e9ef88e0bfb692092db505c95a50fcd32735f4dda8e
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Next Release
|
|
2
2
|
|
|
3
|
+
## 4.14.10
|
|
4
|
+
|
|
5
|
+
* Fix `has_many :through` infinite loop issue
|
|
6
|
+
|
|
7
|
+
## 4.14.9
|
|
8
|
+
|
|
9
|
+
* Support mongoid 5.0.0
|
|
10
|
+
* Do not report association queries immediately after object creation to
|
|
11
|
+
require a preload
|
|
12
|
+
* Detect `counter_cache` for `has_many :through` association
|
|
13
|
+
|
|
14
|
+
## 4.14.8
|
|
15
|
+
|
|
16
|
+
* compatible with `composite_primary_keys` gem
|
|
17
|
+
|
|
18
|
+
## 4.14.7
|
|
19
|
+
|
|
20
|
+
* Fix AR 4.2 SingularAssociation#reader result can be nil
|
|
21
|
+
* `perform_out_of_channel_notifications` should always be triggered
|
|
22
|
+
|
|
23
|
+
## 4.14.6
|
|
24
|
+
|
|
25
|
+
* Fix false positive with `belongs_to` -> `belongs_to` for active\_record 4.2
|
|
26
|
+
* Activate active\_record hacks only when Bullet already start
|
|
27
|
+
|
|
3
28
|
## 4.14.5
|
|
4
29
|
|
|
5
30
|
* Don't execute query when running `to_sql`
|
data/Gemfile.mongoid-5.0
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
gem 'rails', '~> 4.0.0'
|
|
6
|
+
gem 'sqlite3', platforms: [:ruby]
|
|
7
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
+
gem 'mongoid', '~> 5.0.0.beta', github: 'mongoid'
|
|
9
|
+
|
|
10
|
+
gem "rspec"
|
|
11
|
+
|
|
12
|
+
gem 'coveralls', require: false
|
|
13
|
+
|
|
14
|
+
platforms :rbx do
|
|
15
|
+
gem 'rubysl', '~> 2.0'
|
|
16
|
+
gem 'rubinius-developer_tools'
|
|
17
|
+
end
|
data/README.md
CHANGED
|
@@ -36,6 +36,9 @@ or add it into a Gemfile (Bundler):
|
|
|
36
36
|
gem "bullet", :group => "development"
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
**Note**: make sure `bullet` gem is added after activerecord (rails) and
|
|
40
|
+
mongoid.
|
|
41
|
+
|
|
39
42
|
## Configuration
|
|
40
43
|
|
|
41
44
|
Bullet won't do ANYTHING unless you tell it to explicitly. Append to
|
|
@@ -53,6 +56,7 @@ config.after_initialize do
|
|
|
53
56
|
:receiver => 'your_account@jabber.org',
|
|
54
57
|
:show_online_status => true }
|
|
55
58
|
Bullet.rails_logger = true
|
|
59
|
+
Bullet.honeybadger = true
|
|
56
60
|
Bullet.bugsnag = true
|
|
57
61
|
Bullet.airbrake = true
|
|
58
62
|
Bullet.rollbar = true
|
|
@@ -69,6 +73,7 @@ The code above will enable all seven of the Bullet notification systems:
|
|
|
69
73
|
* `Bullet.alert`: pop up a JavaScript alert in the browser
|
|
70
74
|
* `Bullet.bullet_logger`: log to the Bullet log file (Rails.root/log/bullet.log)
|
|
71
75
|
* `Bullet.rails_logger`: add warnings directly to the Rails log
|
|
76
|
+
* `Bullet.honeybadger`: add notifications to Honeybadger
|
|
72
77
|
* `Bullet.bugsnag`: add notifications to bugsnag
|
|
73
78
|
* `Bullet.airbrake`: add notifications to airbrake
|
|
74
79
|
* `Bullet.rollbar`: add notifications to rollbar
|
|
@@ -107,6 +112,22 @@ Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :ass
|
|
|
107
112
|
Bullet.add_whitelist :type => :counter_cache, :class_name => "Country", :association => :cities
|
|
108
113
|
```
|
|
109
114
|
|
|
115
|
+
If you want to skip bullet in some specific controller actions, you can
|
|
116
|
+
do like
|
|
117
|
+
|
|
118
|
+
```ruby
|
|
119
|
+
class ApplicationController < ActionController::Base
|
|
120
|
+
around_action :skip_bullet
|
|
121
|
+
|
|
122
|
+
def skip_bullet
|
|
123
|
+
Bullet.enable = false
|
|
124
|
+
yield
|
|
125
|
+
ensure
|
|
126
|
+
Bullet.enable = true
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
```
|
|
130
|
+
|
|
110
131
|
## Log
|
|
111
132
|
|
|
112
133
|
The Bullet log `log/bullet.log` will look something like this:
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
module Bullet
|
|
2
2
|
module ActiveRecord
|
|
3
|
+
LOAD_TARGET = 'load_target'.freeze
|
|
4
|
+
|
|
3
5
|
def self.enable
|
|
4
6
|
require 'active_record'
|
|
5
7
|
::ActiveRecord::Relation.class_eval do
|
|
@@ -8,12 +10,14 @@ module Bullet
|
|
|
8
10
|
# if select only one object, then the only one object has impossible to cause N+1 query.
|
|
9
11
|
def to_a
|
|
10
12
|
records = origin_to_a
|
|
11
|
-
if
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
if Bullet.start?
|
|
14
|
+
if records.size > 1
|
|
15
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
16
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
|
17
|
+
elsif records.size == 1
|
|
18
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
19
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
|
20
|
+
end
|
|
17
21
|
end
|
|
18
22
|
records
|
|
19
23
|
end
|
|
@@ -24,12 +28,14 @@ module Bullet
|
|
|
24
28
|
# include query for one to many associations.
|
|
25
29
|
# keep this eager loadings.
|
|
26
30
|
def preload_associations(records, associations, preload_options={})
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
if Bullet.start?
|
|
32
|
+
records = [records].flatten.compact.uniq
|
|
33
|
+
return if records.empty?
|
|
34
|
+
records.each do |record|
|
|
35
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
36
|
+
end
|
|
37
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
31
38
|
end
|
|
32
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
33
39
|
origin_preload_associations(records, associations, preload_options={})
|
|
34
40
|
end
|
|
35
41
|
end
|
|
@@ -39,11 +45,13 @@ module Bullet
|
|
|
39
45
|
alias_method :origin_find_with_associations, :find_with_associations
|
|
40
46
|
def find_with_associations
|
|
41
47
|
records = origin_find_with_associations
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
if Bullet.start?
|
|
49
|
+
associations = (@eager_load_values + @includes_values).uniq
|
|
50
|
+
records.each do |record|
|
|
51
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
52
|
+
end
|
|
53
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
45
54
|
end
|
|
46
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
47
55
|
records
|
|
48
56
|
end
|
|
49
57
|
end
|
|
@@ -56,9 +64,11 @@ module Bullet
|
|
|
56
64
|
@bullet_eager_loadings = {}
|
|
57
65
|
records = origin_instantiate(rows)
|
|
58
66
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
if Bullet.start?
|
|
68
|
+
@bullet_eager_loadings.each do |klazz, eager_loadings_hash|
|
|
69
|
+
objects = eager_loadings_hash.keys
|
|
70
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
71
|
+
end
|
|
62
72
|
end
|
|
63
73
|
records
|
|
64
74
|
end
|
|
@@ -67,12 +77,14 @@ module Bullet
|
|
|
67
77
|
def construct_association(record, join, row)
|
|
68
78
|
result = origin_construct_association(record, join, row)
|
|
69
79
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
80
|
+
if Bullet.start?
|
|
81
|
+
associations = join.reflection.name
|
|
82
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
83
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, associations)
|
|
84
|
+
@bullet_eager_loadings[record.class] ||= {}
|
|
85
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
|
86
|
+
@bullet_eager_loadings[record.class][record] << associations
|
|
87
|
+
end
|
|
76
88
|
|
|
77
89
|
result
|
|
78
90
|
end
|
|
@@ -82,31 +94,41 @@ module Bullet
|
|
|
82
94
|
# call one to many associations
|
|
83
95
|
alias_method :origin_load_target, :load_target
|
|
84
96
|
def load_target
|
|
85
|
-
Bullet
|
|
97
|
+
if Bullet.start?
|
|
98
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
99
|
+
end
|
|
86
100
|
origin_load_target
|
|
87
101
|
end
|
|
88
102
|
|
|
89
103
|
alias_method :origin_first, :first
|
|
90
104
|
def first(*args)
|
|
91
|
-
Bullet
|
|
105
|
+
if Bullet.start?
|
|
106
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
107
|
+
end
|
|
92
108
|
origin_first(*args)
|
|
93
109
|
end
|
|
94
110
|
|
|
95
111
|
alias_method :origin_last, :last
|
|
96
112
|
def last(*args)
|
|
97
|
-
Bullet
|
|
113
|
+
if Bullet.start?
|
|
114
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
115
|
+
end
|
|
98
116
|
origin_last(*args)
|
|
99
117
|
end
|
|
100
118
|
|
|
101
119
|
alias_method :origin_empty?, :empty?
|
|
102
120
|
def empty?
|
|
103
|
-
Bullet
|
|
121
|
+
if Bullet.start?
|
|
122
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
123
|
+
end
|
|
104
124
|
origin_empty?
|
|
105
125
|
end
|
|
106
126
|
|
|
107
127
|
alias_method :origin_include?, :include?
|
|
108
128
|
def include?(object)
|
|
109
|
-
Bullet
|
|
129
|
+
if Bullet.start?
|
|
130
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
131
|
+
end
|
|
110
132
|
origin_include?(object)
|
|
111
133
|
end
|
|
112
134
|
end
|
|
@@ -117,15 +139,19 @@ module Bullet
|
|
|
117
139
|
def load_target
|
|
118
140
|
# avoid stack level too deep
|
|
119
141
|
result = origin_load_target
|
|
120
|
-
Bullet
|
|
121
|
-
|
|
142
|
+
if Bullet.start?
|
|
143
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name) unless caller.any? { |c| c.include?(LOAD_TARGET) }
|
|
144
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
145
|
+
end
|
|
122
146
|
result
|
|
123
147
|
end
|
|
124
148
|
|
|
125
149
|
alias_method :origin_set_inverse_instance, :set_inverse_instance
|
|
126
150
|
def set_inverse_instance(record, instance)
|
|
127
|
-
if
|
|
128
|
-
|
|
151
|
+
if Bullet.start?
|
|
152
|
+
if record && we_can_set_the_inverse_on_this?(record)
|
|
153
|
+
Bullet::Detector::NPlusOneQuery.add_inversed_object(record, @reflection.inverse_of.name)
|
|
154
|
+
end
|
|
129
155
|
end
|
|
130
156
|
origin_set_inverse_instance(record, instance)
|
|
131
157
|
end
|
|
@@ -136,7 +162,9 @@ module Bullet
|
|
|
136
162
|
|
|
137
163
|
def has_cached_counter?
|
|
138
164
|
result = origin_has_cached_counter?
|
|
139
|
-
Bullet
|
|
165
|
+
if Bullet.start? && !result
|
|
166
|
+
Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name)
|
|
167
|
+
end
|
|
140
168
|
result
|
|
141
169
|
end
|
|
142
170
|
end
|
|
@@ -145,7 +173,9 @@ module Bullet
|
|
|
145
173
|
alias_method :origin_has_cached_counter?, :has_cached_counter?
|
|
146
174
|
def has_cached_counter?
|
|
147
175
|
result = origin_has_cached_counter?
|
|
148
|
-
Bullet
|
|
176
|
+
if Bullet.start? && !result
|
|
177
|
+
Bullet::Detector::CounterCache.add_counter_cache(@owner, @reflection.name)
|
|
178
|
+
end
|
|
149
179
|
result
|
|
150
180
|
end
|
|
151
181
|
end
|
|
@@ -8,12 +8,14 @@ module Bullet
|
|
|
8
8
|
# if select only one object, then the only one object has impossible to cause N+1 query.
|
|
9
9
|
def to_a
|
|
10
10
|
records = origin_to_a
|
|
11
|
-
if
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
if Bullet.start?
|
|
12
|
+
if records.size > 1
|
|
13
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
14
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
|
15
|
+
elsif records.size == 1
|
|
16
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
17
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
|
18
|
+
end
|
|
17
19
|
end
|
|
18
20
|
records
|
|
19
21
|
end
|
|
@@ -25,12 +27,14 @@ module Bullet
|
|
|
25
27
|
alias_method :origin_initialize, :initialize
|
|
26
28
|
def initialize(records, associations, preload_scope = nil)
|
|
27
29
|
origin_initialize(records, associations, preload_scope)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if Bullet.start?
|
|
31
|
+
records = [records].flatten.compact.uniq
|
|
32
|
+
return if records.empty?
|
|
33
|
+
records.each do |record|
|
|
34
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
35
|
+
end
|
|
36
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
32
37
|
end
|
|
33
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
34
38
|
end
|
|
35
39
|
end
|
|
36
40
|
|
|
@@ -39,11 +43,13 @@ module Bullet
|
|
|
39
43
|
alias_method :origin_find_with_associations, :find_with_associations
|
|
40
44
|
def find_with_associations
|
|
41
45
|
records = origin_find_with_associations
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
if Bullet.start?
|
|
47
|
+
associations = (eager_load_values + includes_values).uniq
|
|
48
|
+
records.each do |record|
|
|
49
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
50
|
+
end
|
|
51
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
45
52
|
end
|
|
46
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
47
53
|
records
|
|
48
54
|
end
|
|
49
55
|
end
|
|
@@ -56,9 +62,11 @@ module Bullet
|
|
|
56
62
|
@bullet_eager_loadings = {}
|
|
57
63
|
records = origin_instantiate(rows)
|
|
58
64
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
if Bullet.start?
|
|
66
|
+
@bullet_eager_loadings.each do |klazz, eager_loadings_hash|
|
|
67
|
+
objects = eager_loadings_hash.keys
|
|
68
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
69
|
+
end
|
|
62
70
|
end
|
|
63
71
|
records
|
|
64
72
|
end
|
|
@@ -67,12 +75,14 @@ module Bullet
|
|
|
67
75
|
def construct_association(record, join, row)
|
|
68
76
|
result = origin_construct_association(record, join, row)
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
if Bullet.start?
|
|
79
|
+
associations = join.reflection.name
|
|
80
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
81
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, associations)
|
|
82
|
+
@bullet_eager_loadings[record.class] ||= {}
|
|
83
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
|
84
|
+
@bullet_eager_loadings[record.class][record] << associations
|
|
85
|
+
end
|
|
76
86
|
|
|
77
87
|
result
|
|
78
88
|
end
|
|
@@ -82,19 +92,25 @@ module Bullet
|
|
|
82
92
|
# call one to many associations
|
|
83
93
|
alias_method :origin_load_target, :load_target
|
|
84
94
|
def load_target
|
|
85
|
-
Bullet
|
|
95
|
+
if Bullet.start?
|
|
96
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
97
|
+
end
|
|
86
98
|
origin_load_target
|
|
87
99
|
end
|
|
88
100
|
|
|
89
101
|
alias_method :origin_empty?, :empty?
|
|
90
102
|
def empty?
|
|
91
|
-
Bullet
|
|
103
|
+
if Bullet.start?
|
|
104
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
105
|
+
end
|
|
92
106
|
origin_empty?
|
|
93
107
|
end
|
|
94
108
|
|
|
95
109
|
alias_method :origin_include?, :include?
|
|
96
110
|
def include?(object)
|
|
97
|
-
Bullet
|
|
111
|
+
if Bullet.start?
|
|
112
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
113
|
+
end
|
|
98
114
|
origin_include?(object)
|
|
99
115
|
end
|
|
100
116
|
end
|
|
@@ -104,8 +120,10 @@ module Bullet
|
|
|
104
120
|
alias_method :origin_reader, :reader
|
|
105
121
|
def reader(force_reload = false)
|
|
106
122
|
result = origin_reader(force_reload)
|
|
107
|
-
Bullet
|
|
108
|
-
|
|
123
|
+
if Bullet.start?
|
|
124
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
125
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
126
|
+
end
|
|
109
127
|
result
|
|
110
128
|
end
|
|
111
129
|
end
|
|
@@ -113,8 +131,10 @@ module Bullet
|
|
|
113
131
|
::ActiveRecord::Associations::Association.class_eval do
|
|
114
132
|
alias_method :origin_set_inverse_instance, :set_inverse_instance
|
|
115
133
|
def set_inverse_instance(record)
|
|
116
|
-
if
|
|
117
|
-
|
|
134
|
+
if Bullet.start?
|
|
135
|
+
if record && invertible_for?(record)
|
|
136
|
+
Bullet::Detector::NPlusOneQuery.add_inversed_object(record, inverse_reflection_for(record).name)
|
|
137
|
+
end
|
|
118
138
|
end
|
|
119
139
|
origin_set_inverse_instance(record)
|
|
120
140
|
end
|
|
@@ -125,7 +145,9 @@ module Bullet
|
|
|
125
145
|
|
|
126
146
|
def has_cached_counter?(reflection = reflection())
|
|
127
147
|
result = origin_has_cached_counter?(reflection)
|
|
128
|
-
Bullet
|
|
148
|
+
if Bullet.start? && !result
|
|
149
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
|
150
|
+
end
|
|
129
151
|
result
|
|
130
152
|
end
|
|
131
153
|
end
|
|
@@ -8,29 +8,43 @@ module Bullet
|
|
|
8
8
|
# if select only one object, then the only one object has impossible to cause N+1 query.
|
|
9
9
|
def to_a
|
|
10
10
|
records = origin_to_a
|
|
11
|
-
if
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
if Bullet.start?
|
|
12
|
+
if records.size > 1
|
|
13
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
14
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
|
15
|
+
elsif records.size == 1
|
|
16
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
17
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
|
18
|
+
end
|
|
17
19
|
end
|
|
18
20
|
records
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
|
|
24
|
+
::ActiveRecord::Persistence.class_eval do
|
|
25
|
+
def save_with_bullet(*args, &proc)
|
|
26
|
+
was_new_record = new_record?
|
|
27
|
+
save_without_bullet(*args, &proc).tap do |result|
|
|
28
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
alias_method_chain :save, :bullet
|
|
32
|
+
end
|
|
33
|
+
|
|
22
34
|
::ActiveRecord::Associations::Preloader.class_eval do
|
|
23
35
|
# include query for one to many associations.
|
|
24
36
|
# keep this eager loadings.
|
|
25
37
|
alias_method :origin_initialize, :initialize
|
|
26
38
|
def initialize(records, associations, preload_scope = nil)
|
|
27
39
|
origin_initialize(records, associations, preload_scope)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
if Bullet.start?
|
|
41
|
+
records = [records].flatten.compact.uniq
|
|
42
|
+
return if records.empty?
|
|
43
|
+
records.each do |record|
|
|
44
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
45
|
+
end
|
|
46
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
32
47
|
end
|
|
33
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
34
48
|
end
|
|
35
49
|
end
|
|
36
50
|
|
|
@@ -39,11 +53,13 @@ module Bullet
|
|
|
39
53
|
alias_method :origin_find_with_associations, :find_with_associations
|
|
40
54
|
def find_with_associations
|
|
41
55
|
records = origin_find_with_associations
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
if Bullet.start?
|
|
57
|
+
associations = (eager_load_values + includes_values).uniq
|
|
58
|
+
records.each do |record|
|
|
59
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
60
|
+
end
|
|
61
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
45
62
|
end
|
|
46
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
47
63
|
records
|
|
48
64
|
end
|
|
49
65
|
end
|
|
@@ -56,9 +72,11 @@ module Bullet
|
|
|
56
72
|
@bullet_eager_loadings = {}
|
|
57
73
|
records = origin_instantiate(rows)
|
|
58
74
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
75
|
+
if Bullet.start?
|
|
76
|
+
@bullet_eager_loadings.each do |klazz, eager_loadings_hash|
|
|
77
|
+
objects = eager_loadings_hash.keys
|
|
78
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
79
|
+
end
|
|
62
80
|
end
|
|
63
81
|
records
|
|
64
82
|
end
|
|
@@ -67,12 +85,14 @@ module Bullet
|
|
|
67
85
|
def construct_association(record, join, row)
|
|
68
86
|
result = origin_construct_association(record, join, row)
|
|
69
87
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
if Bullet.start?
|
|
89
|
+
associations = join.reflection.name
|
|
90
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
91
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, associations)
|
|
92
|
+
@bullet_eager_loadings[record.class] ||= {}
|
|
93
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
|
94
|
+
@bullet_eager_loadings[record.class][record] << associations
|
|
95
|
+
end
|
|
76
96
|
|
|
77
97
|
result
|
|
78
98
|
end
|
|
@@ -82,19 +102,25 @@ module Bullet
|
|
|
82
102
|
# call one to many associations
|
|
83
103
|
alias_method :origin_load_target, :load_target
|
|
84
104
|
def load_target
|
|
85
|
-
Bullet
|
|
105
|
+
if Bullet.start?
|
|
106
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
107
|
+
end
|
|
86
108
|
origin_load_target
|
|
87
109
|
end
|
|
88
110
|
|
|
89
111
|
alias_method :origin_empty?, :empty?
|
|
90
112
|
def empty?
|
|
91
|
-
Bullet
|
|
113
|
+
if Bullet.start?
|
|
114
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
115
|
+
end
|
|
92
116
|
origin_empty?
|
|
93
117
|
end
|
|
94
118
|
|
|
95
119
|
alias_method :origin_include?, :include?
|
|
96
120
|
def include?(object)
|
|
97
|
-
Bullet
|
|
121
|
+
if Bullet.start?
|
|
122
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
123
|
+
end
|
|
98
124
|
origin_include?(object)
|
|
99
125
|
end
|
|
100
126
|
end
|
|
@@ -104,9 +130,11 @@ module Bullet
|
|
|
104
130
|
alias_method :origin_reader, :reader
|
|
105
131
|
def reader(force_reload = false)
|
|
106
132
|
result = origin_reader(force_reload)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
133
|
+
if Bullet.start?
|
|
134
|
+
unless @inversed
|
|
135
|
+
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
136
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
137
|
+
end
|
|
110
138
|
end
|
|
111
139
|
result
|
|
112
140
|
end
|
|
@@ -117,7 +145,9 @@ module Bullet
|
|
|
117
145
|
|
|
118
146
|
def has_cached_counter?(reflection = reflection())
|
|
119
147
|
result = origin_has_cached_counter?(reflection)
|
|
120
|
-
Bullet
|
|
148
|
+
if Bullet.start? && !result
|
|
149
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
|
150
|
+
end
|
|
121
151
|
result
|
|
122
152
|
end
|
|
123
153
|
end
|