bullet 5.4.3 → 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.
@@ -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