bullet 5.4.0 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -92
- data/CHANGELOG.md +10 -0
- data/Gemfile.mongoid-5.0 +1 -1
- data/{Gemfile.mongoid-2.4 → Gemfile.mongoid-6.0} +2 -2
- data/README.md +5 -3
- data/lib/bullet/active_record4.rb +9 -4
- data/lib/bullet/active_record41.rb +12 -8
- data/lib/bullet/active_record42.rb +13 -21
- data/lib/bullet/active_record5.rb +7 -2
- data/lib/bullet/dependency.rb +12 -34
- data/lib/bullet/{mongoid3x.rb → mongoid6x.rb} +3 -3
- data/lib/bullet/notification/n_plus_one_query.rb +3 -3
- data/lib/bullet/notification/unused_eager_loading.rb +12 -7
- data/lib/bullet/rack.rb +6 -1
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +5 -3
- data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +1 -1
- data/spec/bullet_spec.rb +3 -9
- data/spec/integration/counter_cache_spec.rb +7 -0
- data/test.sh +1 -10
- data/update.sh +1 -10
- metadata +4 -18
- data/Gemfile.mongoid-2.5 +0 -15
- data/Gemfile.mongoid-2.6 +0 -15
- data/Gemfile.mongoid-2.7 +0 -15
- data/Gemfile.mongoid-2.8 +0 -15
- data/Gemfile.mongoid-3.0 +0 -15
- data/Gemfile.mongoid-3.1 +0 -15
- data/Gemfile.rails-3.0 +0 -16
- data/Gemfile.rails-3.1 +0 -16
- data/Gemfile.rails-3.2 +0 -16
- data/lib/bullet/active_record3.rb +0 -233
- data/lib/bullet/active_record3x.rb +0 -205
- data/lib/bullet/mongoid2x.rb +0 -56
- data/spec/integration/active_record3/association_spec.rb +0 -745
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
module Bullet
|
|
2
|
-
module ActiveRecord
|
|
3
|
-
def self.enable
|
|
4
|
-
require 'active_record'
|
|
5
|
-
::ActiveRecord::Base.class_eval do
|
|
6
|
-
class <<self
|
|
7
|
-
alias_method :origin_find_by_sql, :find_by_sql
|
|
8
|
-
def find_by_sql(sql, binds = [])
|
|
9
|
-
result = origin_find_by_sql(sql, binds)
|
|
10
|
-
if Bullet.start?
|
|
11
|
-
if result.is_a? Array
|
|
12
|
-
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
13
|
-
Bullet::Detector::CounterCache.add_possible_objects(result)
|
|
14
|
-
elsif result.is_a? ::ActiveRecord::Base
|
|
15
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
|
|
16
|
-
Bullet::Detector::CounterCache.add_impossible_object(result)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
result
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
::ActiveRecord::Relation.class_eval do
|
|
25
|
-
alias_method :origin_to_a, :to_a
|
|
26
|
-
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
|
27
|
-
# if select only one object, then the only one object has impossible to cause N+1 query.
|
|
28
|
-
def to_a
|
|
29
|
-
records = origin_to_a
|
|
30
|
-
if Bullet.start?
|
|
31
|
-
if records.size > 1
|
|
32
|
-
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
33
|
-
Bullet::Detector::CounterCache.add_possible_objects(records)
|
|
34
|
-
elsif records.size == 1
|
|
35
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
36
|
-
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
records
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
::ActiveRecord::Persistence.class_eval do
|
|
44
|
-
alias_method :origin_save, :save
|
|
45
|
-
def save(*args, &proc)
|
|
46
|
-
was_new_record = new_record?
|
|
47
|
-
origin_save(*args, &proc).tap do |result|
|
|
48
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
alias_method :origin_save!, :save!
|
|
53
|
-
def save!(*args, &proc)
|
|
54
|
-
was_new_record = new_record?
|
|
55
|
-
origin_save!(*args, &proc).tap do |result|
|
|
56
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
::ActiveRecord::Associations::Preloader.class_eval do
|
|
62
|
-
# include query for one to many associations.
|
|
63
|
-
# keep this eager loadings.
|
|
64
|
-
alias_method :origin_initialize, :initialize
|
|
65
|
-
def initialize(records, associations, preload_scope = nil)
|
|
66
|
-
origin_initialize(records, associations, preload_scope)
|
|
67
|
-
if Bullet.start?
|
|
68
|
-
records = [records].flatten.compact.uniq
|
|
69
|
-
return if records.empty?
|
|
70
|
-
records.each do |record|
|
|
71
|
-
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
72
|
-
end
|
|
73
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
::ActiveRecord::FinderMethods.class_eval do
|
|
79
|
-
# add includes in scope
|
|
80
|
-
alias_method :origin_find_with_associations, :find_with_associations
|
|
81
|
-
def find_with_associations
|
|
82
|
-
records = origin_find_with_associations
|
|
83
|
-
if Bullet.start?
|
|
84
|
-
associations = (eager_load_values + includes_values).uniq
|
|
85
|
-
records.each do |record|
|
|
86
|
-
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
87
|
-
end
|
|
88
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
89
|
-
end
|
|
90
|
-
records
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
::ActiveRecord::Associations::JoinDependency.class_eval do
|
|
95
|
-
alias_method :origin_instantiate, :instantiate
|
|
96
|
-
alias_method :origin_construct_association, :construct_association
|
|
97
|
-
|
|
98
|
-
def instantiate(rows)
|
|
99
|
-
@bullet_eager_loadings = {}
|
|
100
|
-
records = origin_instantiate(rows)
|
|
101
|
-
|
|
102
|
-
if Bullet.start?
|
|
103
|
-
@bullet_eager_loadings.each do |klazz, eager_loadings_hash|
|
|
104
|
-
objects = eager_loadings_hash.keys
|
|
105
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
records
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# call join associations
|
|
112
|
-
def construct_association(record, join, row)
|
|
113
|
-
result = origin_construct_association(record, join, row)
|
|
114
|
-
|
|
115
|
-
if Bullet.start?
|
|
116
|
-
associations = join.reflection.name
|
|
117
|
-
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
118
|
-
Bullet::Detector::NPlusOneQuery.call_association(record, associations)
|
|
119
|
-
@bullet_eager_loadings[record.class] ||= {}
|
|
120
|
-
@bullet_eager_loadings[record.class][record] ||= Set.new
|
|
121
|
-
@bullet_eager_loadings[record.class][record] << associations
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
result
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
::ActiveRecord::Associations::CollectionAssociation.class_eval do
|
|
129
|
-
# call one to many associations
|
|
130
|
-
alias_method :origin_load_target, :load_target
|
|
131
|
-
def load_target
|
|
132
|
-
if Bullet.start?
|
|
133
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
134
|
-
end
|
|
135
|
-
origin_load_target
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
alias_method :origin_include?, :include?
|
|
139
|
-
def include?(object)
|
|
140
|
-
if Bullet.start?
|
|
141
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
142
|
-
end
|
|
143
|
-
origin_include?(object)
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
::ActiveRecord::Associations::HasManyAssociation.class_eval do
|
|
148
|
-
alias_method :origin_empty?, :empty?
|
|
149
|
-
def empty?
|
|
150
|
-
if Bullet.start? && !has_cached_counter?(@reflection)
|
|
151
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
152
|
-
end
|
|
153
|
-
origin_empty?
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
::ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
|
|
158
|
-
alias_method :origin_empty?, :empty?
|
|
159
|
-
def empty?
|
|
160
|
-
if Bullet.start?
|
|
161
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
162
|
-
end
|
|
163
|
-
origin_empty?
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
::ActiveRecord::Associations::SingularAssociation.class_eval do
|
|
168
|
-
# call has_one and belongs_to associations
|
|
169
|
-
alias_method :origin_reader, :reader
|
|
170
|
-
def reader(force_reload = false)
|
|
171
|
-
result = origin_reader(force_reload)
|
|
172
|
-
if Bullet.start?
|
|
173
|
-
Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
|
|
174
|
-
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
175
|
-
end
|
|
176
|
-
result
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
::ActiveRecord::Associations::Association.class_eval do
|
|
181
|
-
alias_method :origin_set_inverse_instance, :set_inverse_instance
|
|
182
|
-
def set_inverse_instance(record)
|
|
183
|
-
if Bullet.start?
|
|
184
|
-
if record && invertible_for?(record)
|
|
185
|
-
Bullet::Detector::NPlusOneQuery.add_inversed_object(record, inverse_reflection_for(record).name)
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
origin_set_inverse_instance(record)
|
|
189
|
-
end
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
::ActiveRecord::Associations::HasManyAssociation.class_eval do
|
|
193
|
-
alias_method :origin_has_cached_counter?, :has_cached_counter?
|
|
194
|
-
|
|
195
|
-
def has_cached_counter?(reflection = reflection())
|
|
196
|
-
result = origin_has_cached_counter?(reflection)
|
|
197
|
-
if Bullet.start? && !result
|
|
198
|
-
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
|
199
|
-
end
|
|
200
|
-
result
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
end
|
data/lib/bullet/mongoid2x.rb
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
module Bullet
|
|
2
|
-
module Mongoid
|
|
3
|
-
def self.enable
|
|
4
|
-
require 'mongoid'
|
|
5
|
-
|
|
6
|
-
::Mongoid::Contexts::Mongo.class_eval do
|
|
7
|
-
alias_method :origin_first, :first
|
|
8
|
-
alias_method :origin_last, :last
|
|
9
|
-
alias_method :origin_iterate, :iterate
|
|
10
|
-
alias_method :origin_eager_load, :eager_load
|
|
11
|
-
|
|
12
|
-
def first
|
|
13
|
-
result = origin_first
|
|
14
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
|
15
|
-
result
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def last
|
|
19
|
-
result = origin_last
|
|
20
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
|
21
|
-
result
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def iterate(&block)
|
|
25
|
-
records = execute.to_a
|
|
26
|
-
if records.size > 1
|
|
27
|
-
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
28
|
-
elsif records.size == 1
|
|
29
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
30
|
-
end
|
|
31
|
-
origin_iterate(&block)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def eager_load(docs)
|
|
35
|
-
associations = criteria.inclusions.map(&:name)
|
|
36
|
-
docs.each do |doc|
|
|
37
|
-
Bullet::Detector::Association.add_object_associations(doc, associations)
|
|
38
|
-
end
|
|
39
|
-
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
|
|
40
|
-
origin_eager_load(docs)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
::Mongoid::Relations::Accessors.class_eval do
|
|
45
|
-
alias_method :origin_set_relation, :set_relation
|
|
46
|
-
|
|
47
|
-
def set_relation(name, relation)
|
|
48
|
-
if relation && relation.metadata.macro !~ /embed/
|
|
49
|
-
Bullet::Detector::NPlusOneQuery.call_association(self, name)
|
|
50
|
-
end
|
|
51
|
-
origin_set_relation(name, relation)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|