bullet 5.4.3 → 5.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,210 +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
- if result.size > 1
13
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
14
- Bullet::Detector::CounterCache.add_possible_objects(result)
15
- elsif result.size == 1
16
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
17
- Bullet::Detector::CounterCache.add_impossible_object(result.first)
18
- end
19
- elsif result.is_a? ::ActiveRecord::Base
20
- Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
21
- Bullet::Detector::CounterCache.add_impossible_object(result)
22
- end
23
- end
24
- result
25
- end
26
- end
27
- end
28
-
29
- ::ActiveRecord::Relation.class_eval do
30
- alias_method :origin_to_a, :to_a
31
- # if select a collection of objects, then these objects have possible to cause N+1 query.
32
- # if select only one object, then the only one object has impossible to cause N+1 query.
33
- def to_a
34
- records = origin_to_a
35
- if Bullet.start?
36
- if records.size > 1
37
- Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
38
- Bullet::Detector::CounterCache.add_possible_objects(records)
39
- elsif records.size == 1
40
- Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
41
- Bullet::Detector::CounterCache.add_impossible_object(records.first)
42
- end
43
- end
44
- records
45
- end
46
- end
47
-
48
- ::ActiveRecord::Persistence.class_eval do
49
- alias_method :origin_save, :save
50
- def save(*args, &proc)
51
- was_new_record = new_record?
52
- origin_save(*args, &proc).tap do |result|
53
- Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
54
- end
55
- end
56
-
57
- alias_method :origin_save!, :save!
58
- def save!(*args, &proc)
59
- was_new_record = new_record?
60
- origin_save!(*args, &proc).tap do |result|
61
- Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
62
- end
63
- end
64
- end
65
-
66
- ::ActiveRecord::Associations::Preloader.class_eval do
67
- # include query for one to many associations.
68
- # keep this eager loadings.
69
- alias_method :origin_initialize, :initialize
70
- def initialize(records, associations, preload_scope = nil)
71
- origin_initialize(records, associations, preload_scope)
72
- if Bullet.start?
73
- records = [records].flatten.compact.uniq
74
- return if records.empty?
75
- records.each do |record|
76
- Bullet::Detector::Association.add_object_associations(record, associations)
77
- end
78
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
79
- end
80
- end
81
- end
82
-
83
- ::ActiveRecord::FinderMethods.class_eval do
84
- # add includes in scope
85
- alias_method :origin_find_with_associations, :find_with_associations
86
- def find_with_associations
87
- records = origin_find_with_associations
88
- if Bullet.start?
89
- associations = (eager_load_values + includes_values).uniq
90
- records.each do |record|
91
- Bullet::Detector::Association.add_object_associations(record, associations)
92
- end
93
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
94
- end
95
- records
96
- end
97
- end
98
-
99
- ::ActiveRecord::Associations::JoinDependency.class_eval do
100
- alias_method :origin_instantiate, :instantiate
101
- alias_method :origin_construct_association, :construct_association
102
-
103
- def instantiate(rows)
104
- @bullet_eager_loadings = {}
105
- records = origin_instantiate(rows)
106
-
107
- if Bullet.start?
108
- @bullet_eager_loadings.each do |klazz, eager_loadings_hash|
109
- objects = eager_loadings_hash.keys
110
- Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
111
- end
112
- end
113
- records
114
- end
115
-
116
- # call join associations
117
- def construct_association(record, join, row)
118
- result = origin_construct_association(record, join, row)
119
-
120
- if Bullet.start?
121
- associations = join.reflection.name
122
- Bullet::Detector::Association.add_object_associations(record, associations)
123
- Bullet::Detector::NPlusOneQuery.call_association(record, associations)
124
- @bullet_eager_loadings[record.class] ||= {}
125
- @bullet_eager_loadings[record.class][record] ||= Set.new
126
- @bullet_eager_loadings[record.class][record] << associations
127
- end
128
-
129
- result
130
- end
131
- end
132
-
133
- ::ActiveRecord::Associations::CollectionAssociation.class_eval do
134
- # call one to many associations
135
- alias_method :origin_load_target, :load_target
136
- def load_target
137
- if Bullet.start?
138
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
139
- end
140
- origin_load_target
141
- end
142
-
143
- alias_method :origin_include?, :include?
144
- def include?(object)
145
- if Bullet.start?
146
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
147
- end
148
- origin_include?(object)
149
- end
150
- end
151
-
152
- ::ActiveRecord::Associations::HasManyAssociation.class_eval do
153
- alias_method :origin_empty?, :empty?
154
- def empty?
155
- if Bullet.start? && !has_cached_counter?(@reflection)
156
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
157
- end
158
- origin_empty?
159
- end
160
- end
161
-
162
- ::ActiveRecord::Associations::HasAndBelongsToManyAssociation.class_eval do
163
- alias_method :origin_empty?, :empty?
164
- def empty?
165
- if Bullet.start?
166
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
167
- end
168
- origin_empty?
169
- end
170
- end
171
-
172
- ::ActiveRecord::Associations::SingularAssociation.class_eval do
173
- # call has_one and belongs_to associations
174
- alias_method :origin_reader, :reader
175
- def reader(force_reload = false)
176
- result = origin_reader(force_reload)
177
- if Bullet.start?
178
- Bullet::Detector::NPlusOneQuery.call_association(@owner, @reflection.name)
179
- Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
180
- end
181
- result
182
- end
183
- end
184
-
185
- ::ActiveRecord::Associations::Association.class_eval do
186
- alias_method :origin_set_inverse_instance, :set_inverse_instance
187
- def set_inverse_instance(record)
188
- if Bullet.start?
189
- if record && invertible_for?(record)
190
- Bullet::Detector::NPlusOneQuery.add_inversed_object(record, inverse_reflection_for(record).name)
191
- end
192
- end
193
- origin_set_inverse_instance(record)
194
- end
195
- end
196
-
197
- ::ActiveRecord::Associations::HasManyAssociation.class_eval do
198
- alias_method :origin_has_cached_counter?, :has_cached_counter?
199
-
200
- def has_cached_counter?(reflection = reflection())
201
- result = origin_has_cached_counter?(reflection)
202
- if Bullet.start? && !result
203
- Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
204
- end
205
- result
206
- end
207
- end
208
- end
209
- end
210
- end
@@ -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
@@ -1,745 +0,0 @@
1
- require 'spec_helper'
2
-
3
- if !mongoid? && active_record3?
4
- describe Bullet::Detector::Association, 'has_many' do
5
- context "post => comments" do
6
- it "should detect non preload post => comments" do
7
- Post.all.each do |post|
8
- post.comments.map(&:name)
9
- end
10
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
11
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
12
-
13
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
14
- end
15
-
16
- it "should detect non preload post => comments for find_by_sql" do
17
- Post.find_by_sql("SELECT * FROM posts").each do |post|
18
- post.comments.map(&:name)
19
- end
20
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
21
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
22
-
23
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
24
- end
25
-
26
- it "should detect preload with post => comments" do
27
- Post.includes(:comments).each do |post|
28
- post.comments.map(&:name)
29
- end
30
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
31
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
32
-
33
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
34
- end
35
-
36
- it "should detect unused preload post => comments" do
37
- Post.includes(:comments).map(&:name)
38
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
39
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
40
-
41
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
42
- end
43
-
44
- it "should not detect unused preload post => comments" do
45
- Post.all.map(&:name)
46
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
47
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
48
-
49
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
50
- end
51
-
52
- it "should not detect non preload comment => post with inverse_of" do
53
- Post.includes(:comments).each do |post|
54
- post.comments.each do |comment|
55
- comment.name
56
- comment.post.name
57
- end
58
- end
59
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
60
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
61
-
62
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
63
- end
64
-
65
- it "should detect non preload post => comments with empty?" do
66
- Post.all.each do |post|
67
- post.comments.empty?
68
- end
69
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
70
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
71
-
72
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
73
- end
74
-
75
- it "should detect non preload post => comments with include?" do
76
- comment = Comment.last
77
- Post.all.each do |post|
78
- post.comments.include?(comment)
79
- end
80
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
81
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
82
-
83
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
84
- end
85
-
86
- it "should not detect unused preload person => pets with empty?" do
87
- Person.all.each do |person|
88
- person.pets.empty?
89
- end
90
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
91
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
92
-
93
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
94
- end
95
- end
96
-
97
- context "category => posts => comments" do
98
- it "should detect non preload category => posts => comments" do
99
- Category.all.each do |category|
100
- category.posts.each do |post|
101
- post.comments.map(&:name)
102
- end
103
- end
104
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
105
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
106
-
107
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :posts)
108
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
109
- end
110
-
111
- it "should detect preload category => posts, but no post => comments" do
112
- Category.includes(:posts).each do |category|
113
- category.posts.each do |post|
114
- post.comments.map(&:name)
115
- end
116
- end
117
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
118
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
119
-
120
- expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Category, :posts)
121
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
122
- end
123
-
124
- it "should detect preload with category => posts => comments" do
125
- Category.includes({:posts => :comments}).each do |category|
126
- category.posts.each do |post|
127
- post.comments.map(&:name)
128
- end
129
- end
130
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
131
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
132
-
133
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
134
- end
135
-
136
- it "should detect preload with category => posts => comments with posts.id > 0" do
137
- Category.includes({:posts => :comments}).where('posts.id > 0').each do |category|
138
- category.posts.each do |post|
139
- post.comments.map(&:name)
140
- end
141
- end
142
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
143
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
144
-
145
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
146
- end
147
-
148
- it "should detect unused preload with category => posts => comments" do
149
- Category.includes({:posts => :comments}).map(&:name)
150
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
151
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
152
-
153
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
154
- end
155
-
156
- it "should detect unused preload with post => commnets, no category => posts" do
157
- Category.includes({:posts => :comments}).each do |category|
158
- category.posts.map(&:name)
159
- end
160
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
161
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
162
-
163
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
164
- end
165
- end
166
-
167
- context "category => posts, category => entries" do
168
- it "should detect non preload with category => [posts, entries]" do
169
- Category.all.each do |category|
170
- category.posts.map(&:name)
171
- category.entries.map(&:name)
172
- end
173
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
174
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
175
-
176
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :posts)
177
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :entries)
178
- end
179
-
180
- it "should detect preload with category => posts, but not with category => entries" do
181
- Category.includes(:posts).each do |category|
182
- category.posts.map(&:name)
183
- category.entries.map(&:name)
184
- end
185
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
186
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
187
-
188
- expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Category, :posts)
189
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Category, :entries)
190
- end
191
-
192
- it "should detect preload with category => [posts, entries]" do
193
- Category.includes([:posts, :entries]).each do |category|
194
- category.posts.map(&:name)
195
- category.entries.map(&:name)
196
- end
197
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
198
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
199
-
200
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
201
- end
202
-
203
- it "should detect unused preload with category => [posts, entries]" do
204
- Category.includes([:posts, :entries]).map(&:name)
205
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
206
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :posts)
207
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :entries)
208
-
209
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
210
- end
211
-
212
- it "should detect unused preload with category => entries, but not with category => posts" do
213
- Category.includes([:posts, :entries]).each do |category|
214
- category.posts.map(&:name)
215
- end
216
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
217
- expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Category, :posts)
218
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Category, :entries)
219
-
220
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
221
- end
222
- end
223
-
224
- context "post => comment" do
225
- it "should detect unused preload with post => comments" do
226
- Post.includes(:comments).each do |post|
227
- post.comments.first.name if post.comments.first
228
- end
229
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
230
- expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :comments)
231
-
232
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
233
- end
234
-
235
- it "should detect preload with post => commnets" do
236
- Post.first.comments.map(&:name)
237
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
238
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
239
-
240
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
241
- end
242
- end
243
-
244
- context "category => posts => writer" do
245
- it "should not detect unused preload associations" do
246
- category = Category.includes({:posts => :writer}).order("id DESC").find_by_name('first')
247
- category.posts.map do |post|
248
- post.name
249
- post.writer.name
250
- end
251
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
252
- expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Category, :posts)
253
- expect(Bullet::Detector::Association).not_to be_unused_preload_associations_for(Post, :writer)
254
-
255
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
256
- end
257
- end
258
-
259
- context "scope for_category_name" do
260
- it "should detect preload with post => category" do
261
- Post.in_category_name('first').each do |post|
262
- post.category.name
263
- end
264
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
265
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
266
-
267
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
268
- end
269
-
270
- it "should not be unused preload post => category" do
271
- Post.in_category_name('first').all.map(&:name)
272
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
273
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
274
-
275
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
276
- end
277
- end
278
-
279
- context "scope preload_comments" do
280
- it "should detect preload post => comments with scope" do
281
- Post.preload_comments.each do |post|
282
- post.comments.map(&:name)
283
- end
284
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
285
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
286
-
287
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
288
- end
289
-
290
- it "should detect unused preload with scope" do
291
- Post.preload_comments.map(&:name)
292
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
293
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
294
-
295
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
296
- end
297
- end
298
- end
299
-
300
- describe Bullet::Detector::Association, 'belongs_to' do
301
- context "comment => post" do
302
- it "should detect non preload with comment => post" do
303
- Comment.all.each do |comment|
304
- comment.post.name
305
- end
306
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
307
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
308
-
309
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
310
- end
311
-
312
- it "should detect preload with one comment => post" do
313
- Comment.first.post.name
314
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
315
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
316
-
317
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
318
- end
319
-
320
- it "should dtect preload with comment => post" do
321
- Comment.includes(:post).each do |comment|
322
- comment.post.name
323
- end
324
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
325
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
326
-
327
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
328
- end
329
-
330
- it "should not detect preload with comment => post" do
331
- Comment.all.map(&:name)
332
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
333
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
334
-
335
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
336
- end
337
-
338
- it "should detect unused preload with comments => post" do
339
- Comment.includes(:post).map(&:name)
340
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
341
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Comment, :post)
342
-
343
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
344
- end
345
- end
346
-
347
- context "comment => post => category" do
348
- it "should detect non preload association with comment => post" do
349
- Comment.all.each do |comment|
350
- comment.post.category.name
351
- end
352
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
353
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
354
-
355
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Comment, :post)
356
- end
357
-
358
- it "should not detect non preload association with only one comment" do
359
- Comment.first.post.category.name
360
-
361
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
362
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
363
-
364
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
365
- end
366
-
367
- it "should detect non preload association with post => category" do
368
- Comment.includes(:post).each do |comment|
369
- comment.post.category.name
370
- end
371
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
372
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
373
-
374
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :category)
375
- end
376
-
377
- it "should not detect unpreload association" do
378
- Comment.includes(:post => :category).each do |comment|
379
- comment.post.category.name
380
- end
381
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
382
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
383
-
384
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
385
- end
386
- end
387
-
388
- context "comment => author, post => writer" do
389
- it "should detect non preloaded writer" do
390
- Comment.includes([:author, :post]).where(["base_users.id = ?", BaseUser.first]).each do |comment|
391
- comment.post.writer.name
392
- end
393
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
394
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
395
-
396
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :writer)
397
- end
398
-
399
- it "should detect unused preload with comment => author" do
400
- Comment.includes([:author, {:post => :writer}]).where(["base_users.id = ?", BaseUser.first]).each do |comment|
401
- comment.post.writer.name
402
- end
403
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
404
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
405
-
406
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
407
- end
408
-
409
- it "should detect non preloading with writer => newspaper" do
410
- Comment.all(:include => {:post => :writer}, :conditions => "posts.name like '%first%'").each do |comment|
411
- comment.post.writer.newspaper.name
412
- end
413
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
414
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
415
-
416
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Writer, :newspaper)
417
- end
418
-
419
- it "should not raise a stack error from posts to category" do
420
- expect {
421
- Comment.includes({:post => :category}).each do |com|
422
- com.post.category
423
- end
424
- }.not_to raise_error
425
- end
426
- end
427
- end
428
-
429
- describe Bullet::Detector::Association, 'has_and_belongs_to_many' do
430
- context "students <=> teachers" do
431
- it "should detect non preload associations" do
432
- Student.all.each do |student|
433
- student.teachers.map(&:name)
434
- end
435
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
436
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
437
-
438
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Student, :teachers)
439
- end
440
-
441
- it "should detect preload associations" do
442
- Student.includes(:teachers).each do |student|
443
- student.teachers.map(&:name)
444
- end
445
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
446
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
447
-
448
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
449
- end
450
-
451
- it "should detect unused preload associations" do
452
- Student.includes(:teachers).map(&:name)
453
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
454
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Student, :teachers)
455
-
456
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
457
- end
458
-
459
- it "should detect no unused preload associations" do
460
- Student.all.map(&:name)
461
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
462
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
463
-
464
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
465
- end
466
-
467
- it "should detect non preload student => teachers with empty?" do
468
- Student.all.each do |student|
469
- student.teachers.empty?
470
- end
471
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
472
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
473
-
474
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Student, :teachers)
475
- end
476
- end
477
- end
478
-
479
- describe Bullet::Detector::Association, 'has_many :through' do
480
- context "firm => clients" do
481
- it "should detect non preload associations" do
482
- Firm.all.each do |firm|
483
- firm.clients.map(&:name)
484
- end
485
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
486
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
487
-
488
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Firm, :clients)
489
- end
490
-
491
- it "should detect preload associations" do
492
- Firm.includes(:clients).each do |firm|
493
- firm.clients.map(&:name)
494
- end
495
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
496
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
497
-
498
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
499
- end
500
-
501
- it "should not detect preload associations" do
502
- Firm.all.map(&:name)
503
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
504
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
505
-
506
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
507
- end
508
-
509
- it "should detect unused preload associations" do
510
- Firm.includes(:clients).map(&:name)
511
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
512
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Firm, :clients)
513
-
514
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
515
- end
516
- end
517
- end
518
-
519
- describe Bullet::Detector::Association, "has_one" do
520
- context "company => address" do
521
- it "should detect non preload association" do
522
- Company.all.each do |company|
523
- company.address.name
524
- end
525
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
526
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
527
-
528
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Company, :address)
529
- end
530
-
531
- it "should detect preload association" do
532
- Company.includes(:address).each do |company|
533
- company.address.name
534
- end
535
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
536
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
537
-
538
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
539
- end
540
-
541
- it "should not detect preload association" do
542
- Company.all.map(&:name)
543
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
544
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
545
-
546
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
547
- end
548
-
549
- it "should detect unused preload association" do
550
- Company.includes(:address).map(&:name)
551
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
552
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Company, :address)
553
-
554
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
555
- end
556
- end
557
- end
558
-
559
- describe Bullet::Detector::Association, "call one association that in possible objects" do
560
- it "should not detect preload association" do
561
- Post.all
562
- Post.first.comments.map(&:name)
563
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
564
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
565
-
566
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
567
- end
568
- end
569
-
570
- describe Bullet::Detector::Association, "query immediately after creation" do
571
- context "with save" do
572
- context "document => children" do
573
- it 'should not detect non preload associations' do
574
- document1 = Document.new
575
- document1.children.build
576
- document1.save
577
-
578
- document2 = Document.new(parent: document1)
579
- document2.save
580
- document2.parent
581
-
582
- document1.children.each.first
583
-
584
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
585
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
586
-
587
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
588
- end
589
- end
590
- end
591
-
592
- context "with save!" do
593
- context "document => children" do
594
- it 'should not detect non preload associations' do
595
- document1 = Document.new
596
- document1.children.build
597
- document1.save!
598
-
599
- document2 = Document.new(parent: document1)
600
- document2.save!
601
- document2.parent
602
-
603
- document1.children.each.first
604
-
605
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
606
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
607
-
608
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
609
- end
610
- end
611
- end
612
- end
613
-
614
- describe Bullet::Detector::Association, "STI" do
615
- context "page => author" do
616
- it "should detect non preload associations" do
617
- Page.all.each do |page|
618
- page.author.name
619
- end
620
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
621
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
622
-
623
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Page, :author)
624
- end
625
-
626
- it "should detect preload associations" do
627
- Page.includes(:author).each do |page|
628
- page.author.name
629
- end
630
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
631
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
632
-
633
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
634
- end
635
-
636
- it "should detect unused preload associations" do
637
- Page.includes(:author).map(&:name)
638
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
639
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Page, :author)
640
-
641
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
642
- end
643
-
644
- it "should not detect preload associations" do
645
- Page.all.map(&:name)
646
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
647
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
648
-
649
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
650
- end
651
- end
652
-
653
- context "disable n plus one query" do
654
- before { Bullet.n_plus_one_query_enable = false }
655
- after { Bullet.n_plus_one_query_enable = true }
656
-
657
- it "should not detect n plus one query" do
658
- Post.all.each do |post|
659
- post.comments.map(&:name)
660
- end
661
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
662
-
663
- expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
664
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
665
- end
666
-
667
- it "should still detect unused eager loading" do
668
- Post.includes(:comments).map(&:name)
669
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
670
-
671
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
672
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
673
- end
674
- end
675
-
676
- context "disable unused eager loading" do
677
- before { Bullet.unused_eager_loading_enable = false }
678
- after { Bullet.unused_eager_loading_enable = true }
679
-
680
- it "should not detect unused eager loading" do
681
- Post.includes(:comments).map(&:name)
682
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
683
-
684
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
685
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
686
- end
687
-
688
- it "should still detect n plus one query" do
689
- Post.all.each do |post|
690
- post.comments.map(&:name)
691
- end
692
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
693
-
694
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
695
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
696
- end
697
- end
698
-
699
- context "whitelist n plus one query" do
700
- before { Bullet.add_whitelist :type => :n_plus_one_query, :class_name => "Post", :association => :comments }
701
- after { Bullet.clear_whitelist }
702
-
703
- it "should not detect n plus one query" do
704
- Post.all.each do |post|
705
- post.comments.map(&:name)
706
- end
707
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
708
-
709
- expect(Bullet::Detector::Association).not_to be_detecting_unpreloaded_association_for(Post, :comments)
710
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
711
- end
712
-
713
- it "should still detect unused eager loading" do
714
- Post.includes(:comments).map(&:name)
715
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
716
-
717
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
718
- expect(Bullet::Detector::Association).to be_unused_preload_associations_for(Post, :comments)
719
- end
720
- end
721
-
722
- context "whitelist unused eager loading" do
723
- before { Bullet.add_whitelist :type => :unused_eager_loading, :class_name => "Post", :association => :comments }
724
- after { Bullet.clear_whitelist }
725
-
726
- it "should not detect unused eager loading" do
727
- Post.includes(:comments).map(&:name)
728
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
729
-
730
- expect(Bullet::Detector::Association).to be_completely_preloading_associations
731
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
732
- end
733
-
734
- it "should still detect n plus one query" do
735
- Post.all.each do |post|
736
- post.comments.map(&:name)
737
- end
738
- Bullet::Detector::UnusedEagerLoading.check_unused_preload_associations
739
-
740
- expect(Bullet::Detector::Association).to be_detecting_unpreloaded_association_for(Post, :comments)
741
- expect(Bullet::Detector::Association).not_to be_has_unused_preload_associations
742
- end
743
- end
744
- end
745
- end