bullet 2.0.0.beta.2 → 2.0.1

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.
Files changed (41) hide show
  1. data/MIT-LICENSE +1 -1
  2. data/README.textile +38 -8
  3. data/README_for_rails2.textile +19 -3
  4. data/lib/bullet/action_controller2.rb +4 -4
  5. data/lib/bullet/active_record2.rb +16 -16
  6. data/lib/bullet/active_record3.rb +16 -25
  7. data/lib/bullet/detector/association.rb +135 -0
  8. data/lib/bullet/detector/base.rb +19 -0
  9. data/lib/bullet/detector/counter.rb +43 -0
  10. data/lib/bullet/detector/n_plus_one_query.rb +39 -0
  11. data/lib/bullet/detector/unused_eager_association.rb +39 -0
  12. data/lib/bullet/detector.rb +9 -0
  13. data/lib/bullet/notification/base.rb +57 -0
  14. data/lib/bullet/notification/counter_cache.rb +13 -0
  15. data/lib/bullet/notification/n_plus_one_query.rb +32 -0
  16. data/lib/bullet/notification/unused_eager_loading.rb +14 -0
  17. data/lib/bullet/notification.rb +4 -79
  18. data/lib/bullet/notification_collector.rb +25 -0
  19. data/lib/bullet/rack.rb +44 -0
  20. data/lib/bullet/registry/association.rb +16 -0
  21. data/lib/bullet/registry/base.rb +39 -0
  22. data/lib/bullet/registry/object.rb +15 -0
  23. data/lib/bullet/registry.rb +7 -0
  24. data/lib/bullet/version.rb +5 -0
  25. data/lib/bullet.rb +63 -42
  26. metadata +60 -42
  27. data/Rakefile +0 -34
  28. data/VERSION +0 -1
  29. data/bullet.gemspec +0 -67
  30. data/lib/bullet/association.rb +0 -294
  31. data/lib/bullet/counter.rb +0 -101
  32. data/lib/bullet/logger.rb +0 -9
  33. data/lib/bulletware.rb +0 -42
  34. data/rails/init.rb +0 -1
  35. data/spec/bullet/association_for_chris_spec.rb +0 -96
  36. data/spec/bullet/association_for_peschkaj_spec.rb +0 -86
  37. data/spec/bullet/association_spec.rb +0 -1043
  38. data/spec/bullet/counter_spec.rb +0 -136
  39. data/spec/spec.opts +0 -3
  40. data/spec/spec_helper.rb +0 -45
  41. data/tasks/bullet_tasks.rake +0 -9
@@ -1,1043 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
-
3
- ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
4
-
5
- describe Bullet::Association, 'has_many' do
6
-
7
- def setup_db
8
- ActiveRecord::Schema.define(:version => 1) do
9
- create_table :categories do |t|
10
- t.column :name, :string
11
- end
12
-
13
- create_table :posts do |t|
14
- t.column :name, :string
15
- t.column :category_id, :integer
16
- t.column :writer_id, :integer
17
- end
18
-
19
- create_table :comments do |t|
20
- t.column :name, :string
21
- t.column :post_id, :integer
22
- t.column :author_id, :integer
23
- end
24
-
25
- create_table :entries do |t|
26
- t.column :name, :string
27
- t.column :category_id, :integer
28
- end
29
-
30
- create_table :base_users do |t|
31
- t.column :name, :string
32
- t.column :type, :string
33
- t.column :newspaper_id, :integer
34
- end
35
- create_table :newspapers do |t|
36
- t.column :name, :string
37
- end
38
- end
39
- end
40
-
41
- def teardown_db
42
- ActiveRecord::Base.connection.tables.each do |table|
43
- ActiveRecord::Base.connection.drop_table(table)
44
- end
45
- end
46
-
47
- class Category < ActiveRecord::Base
48
- has_many :posts
49
- has_many :entries
50
- end
51
-
52
- class Post < ActiveRecord::Base
53
- belongs_to :category
54
- has_many :comments
55
- belongs_to :writer
56
-
57
-
58
- scope :preload_posts, lambda { includes(:comments) }
59
- scope :in_category_name, lambda { |name|
60
- where(['categories.name = ?', name]).includes(:category)
61
- }
62
- end
63
-
64
- class Entry < ActiveRecord::Base
65
- belongs_to :category
66
- end
67
-
68
- class Comment < ActiveRecord::Base
69
- belongs_to :post
70
- belongs_to :author, :class_name => "BaseUser"
71
- end
72
-
73
- class BaseUser < ActiveRecord::Base
74
- has_many :comments
75
- has_many :posts
76
- belongs_to :newspaper
77
- end
78
-
79
- class Newspaper < ActiveRecord::Base
80
- has_many :writers, :class_name => "BaseUser"
81
- end
82
-
83
- class Writer < BaseUser
84
- end
85
-
86
- before(:all) do
87
- setup_db
88
-
89
- newspaper1 = Newspaper.create(:name => "First Newspaper")
90
- newspaper2 = Newspaper.create(:name => "Second Newspaper")
91
-
92
- writer1 = Writer.create(:name => 'first', :newspaper => newspaper1)
93
- writer2 = Writer.create(:name => 'second', :newspaper => newspaper2)
94
- user1 = BaseUser.create(:name => 'third', :newspaper => newspaper1)
95
- user2 = BaseUser.create(:name => 'fourth', :newspaper => newspaper2)
96
-
97
-
98
- category1 = Category.create(:name => 'first')
99
- category2 = Category.create(:name => 'second')
100
-
101
- post1 = category1.posts.create(:name => 'first', :writer => writer1)
102
- post1a = category1.posts.create(:name => 'like first', :writer => writer2)
103
- post2 = category2.posts.create(:name => 'second', :writer => writer2)
104
-
105
- comment1 = post1.comments.create(:name => 'first', :author => writer1)
106
- comment2 = post1.comments.create(:name => 'first2', :author => writer1)
107
- comment3 = post1.comments.create(:name => 'first3', :author => writer1)
108
- comment4 = post1.comments.create(:name => 'second', :author => writer2)
109
- comment8 = post1a.comments.create(:name => "like first 1", :author => writer1)
110
- comment9 = post1a.comments.create(:name => "like first 2", :author => writer2)
111
- comment5 = post2.comments.create(:name => 'third', :author => user1)
112
- comment6 = post2.comments.create(:name => 'fourth', :author => user2)
113
- comment7 = post2.comments.create(:name => 'fourth', :author => writer1)
114
-
115
- entry1 = category1.entries.create(:name => 'first')
116
- entry2 = category1.entries.create(:name => 'second')
117
- end
118
-
119
- after(:all) do
120
- teardown_db
121
- end
122
-
123
- before(:each) do
124
- Bullet::Association.start_request
125
- end
126
-
127
- after(:each) do
128
- Bullet::Association.end_request
129
- end
130
-
131
- # FIXME: setup and teardown are not inherited by context
132
- # context "for unused cases" do
133
- #If you have the same record created twice with different includes
134
- # the hash value get's accumulated includes, which leads to false Unused eager loading
135
- #it "should not incorrectly mark associations as unused when multiple object instances" do
136
- #comments_with_author = Comment.includes(:author)
137
- #comments_with_post = Comment.includes(:post)
138
- #comments_with_author.each { |c| c.author.name }
139
- #comments_with_author.each { |c| c.post.name }
140
- #Bullet::Association.check_unused_preload_associations
141
- #Bullet::Association.should be_unused_preload_associations_for(Comment, :post)
142
- #Bullet::Association.should be_detecting_unpreloaded_association_for(Comment, :post)
143
- #end
144
-
145
- # same as above with different Models being queried
146
- #it "should not incorrectly mark associations as unused when multiple object instances different Model" do
147
- #post_with_comments = Post.includes(:comments)
148
- #comments_with_author = Comment.includes(:author)
149
- #post_with_comments.each { |p| p.comments.first.author.name }
150
- #comments_with_author.each { |c| c.name }
151
- #Bullet::Association.check_unused_preload_associations
152
- #Bullet::Association.should be_unused_preload_associations_for(Comment, :author)
153
- #Bullet::Association.should be_detecting_unpreloaded_association_for(Comment, :author)
154
- #end
155
-
156
- # this test passes right now. But is a regression test to ensure that if only a small set of returned records
157
- # is not used that a unused preload association error is not generated
158
- it "should not have unused when small set of returned records are discarded" do
159
- comments_with_author = Comment.includes(:author)
160
- comment_collection = comments_with_author.limit(2)
161
- comment_collection.collect { |com| com.author.name }
162
- Bullet::Association.check_unused_preload_associations
163
- Bullet::Association.should_not be_unused_preload_associations_for(Comment, :author)
164
- end
165
- # end
166
-
167
-
168
- # FIXME: setup and teardown are not inherited by context
169
- # context "comments => posts => category" do
170
-
171
- # this happens because the post isn't a possible object even though the writer is access through the post
172
- # which leads to an 1+N queries
173
- it "should detect unpreloaded writer" do
174
- Comment.includes([:author, :post]).where(["base_users.id = ?", BaseUser.first]).each do |com|
175
- com.post.writer.name
176
- end
177
- Bullet::Association.should be_detecting_unpreloaded_association_for(Post, :writer)
178
- end
179
-
180
- # this happens because the comment doesn't break down the hash into keys
181
- # properly creating an association from comment to post
182
- it "should detect preload of comment => post" do
183
- comments = Comment.includes([:author, {:post => :writer}]).where(["base_users.id = ?", BaseUser.first]).each do |com|
184
- com.post.writer.name
185
- end
186
- Bullet::Association.should_not be_detecting_unpreloaded_association_for(Comment, :post)
187
- Bullet::Association.should be_completely_preloading_associations
188
- end
189
-
190
- it "should detect preload of post => writer" do
191
- comments = Comment.includes([:author, {:post => :writer}]).where(["base_users.id = ?", BaseUser.first]).each do |com|
192
- com.post.writer.name
193
- end
194
- Bullet::Association.should be_creating_object_association_for(comments.first, :author)
195
- Bullet::Association.should_not be_detecting_unpreloaded_association_for(Post, :writer)
196
- Bullet::Association.should be_completely_preloading_associations
197
- end
198
-
199
- # To flyerhzm: This does not detect that newspaper is unpreloaded. The association is
200
- # not within possible objects, and thus cannot be detected as unpreloaded
201
- it "should detect unpreloading of writer => newspaper" do
202
- comments = Comment.all(:include => {:post => :writer}, :conditions => "posts.name like '%first%'").each do |com|
203
- com.post.writer.newspaper.name
204
- end
205
- Bullet::Association.should be_detecting_unpreloaded_association_for(Writer, :newspaper)
206
- end
207
-
208
- # when we attempt to access category, there is an infinite overflow because load_target is hijacked leading to
209
- # a repeating loop of calls in this test
210
- it "should not raise a stack error from posts to category" do
211
- lambda {
212
- Comment.includes({:post => :category}).each do |com|
213
- com.post.category
214
- end
215
- }.should_not raise_error(SystemStackError)
216
- end
217
- # end
218
-
219
- # FIXME: setup and teardown are not inherited by context
220
- # context "post => comments" do
221
- it "should detect preload with post => comments" do
222
- Post.includes(:comments).each do |post|
223
- post.comments.collect(&:name)
224
- end
225
- Bullet::Association.should_not be_has_unpreload_associations
226
- end
227
-
228
- it "should detect no preload post => comments" do
229
- Post.all.each do |post|
230
- post.comments.collect(&:name)
231
- end
232
- Bullet::Association.should be_has_unpreload_associations
233
- end
234
-
235
- it "should detect unused preload post => comments for post" do
236
- Post.includes(:comments).collect(&:name)
237
- Bullet::Association.check_unused_preload_associations
238
- Bullet::Association.should be_has_unused_preload_associations
239
- end
240
-
241
- it "should detect no unused preload post => comments for post" do
242
- Post.all.collect(&:name)
243
- Bullet::Association.check_unused_preload_associations
244
- Bullet::Association.should_not be_has_unused_preload_associations
245
- end
246
-
247
- it "should detect no unused preload post => comments for comment" do
248
- Post.all.each do |post|
249
- post.comments.collect(&:name)
250
- end
251
- Bullet::Association.check_unused_preload_associations
252
- Bullet::Association.should_not be_has_unused_preload_associations
253
-
254
- Bullet::Association.end_request
255
- Bullet::Association.start_request
256
-
257
- Post.all.each do |post|
258
- post.comments.collect(&:name)
259
- end
260
- Bullet::Association.check_unused_preload_associations
261
- Bullet::Association.should_not be_has_unused_preload_associations
262
- end
263
- # end
264
-
265
- # FIXME: setup and teardown are not inherited by context
266
- # context "category => posts => comments" do
267
- it "should detect preload with category => posts => comments" do
268
- Category.includes({:posts => :comments}).each do |category|
269
- category.posts.each do |post|
270
- post.comments.collect(&:name)
271
- end
272
- end
273
- Bullet::Association.should_not be_has_unpreload_associations
274
- end
275
-
276
- it "should detect preload category => posts, but no post => comments" do
277
- Category.includes(:posts).each do |category|
278
- category.posts.each do |post|
279
- post.comments.collect(&:name)
280
- end
281
- end
282
- Bullet::Association.should be_has_unpreload_associations
283
- end
284
-
285
- it "should detect no preload category => posts => comments" do
286
- Category.all.each do |category|
287
- category.posts.each do |post|
288
- post.comments.collect(&:name)
289
- end
290
- end
291
- Bullet::Association.should be_has_unpreload_associations
292
- end
293
-
294
- it "should detect unused preload with category => posts => comments" do
295
- Category.includes({:posts => :comments}).collect(&:name)
296
- Bullet::Association.check_unused_preload_associations
297
- Bullet::Association.should be_has_unused_preload_associations
298
- end
299
-
300
- it "should detect unused preload with post => commnets, no category => posts" do
301
- Category.includes({:posts => :comments}).each do |category|
302
- category.posts.collect(&:name)
303
- end
304
- Bullet::Association.check_unused_preload_associations
305
- Bullet::Association.should be_has_unused_preload_associations
306
- end
307
-
308
- it "should no detect preload with category => posts => comments" do
309
- Category.all.each do |category|
310
- category.posts.each do |post|
311
- post.comments.collect(&:name)
312
- end
313
- end
314
- Bullet::Association.check_unused_preload_associations
315
- Bullet::Association.should_not be_has_unused_preload_associations
316
- end
317
- # end
318
-
319
- # FIXME: setup and teardown are not inherited by context
320
- # context "category => posts, category => entries" do
321
- it "should detect preload with category => [posts, entries]" do
322
- Category.includes([:posts, :entries]).each do |category|
323
- category.posts.collect(&:name)
324
- category.entries.collect(&:name)
325
- end
326
- Bullet::Association.should_not be_has_unpreload_associations
327
- end
328
-
329
- it "should detect preload with category => posts, but no category => entries" do
330
- Category.includes(:posts).each do |category|
331
- category.posts.collect(&:name)
332
- category.entries.collect(&:name)
333
- end
334
- Bullet::Association.should be_has_unpreload_associations
335
- end
336
-
337
- it "should detect no preload with category => [posts, entries]" do
338
- Category.all.each do |category|
339
- category.posts.collect(&:name)
340
- category.entries.collect(&:name)
341
- end
342
- Bullet::Association.should be_has_unpreload_associations
343
- end
344
-
345
- it "should detect unused with category => [posts, entries]" do
346
- Category.includes([:posts, :entries]).collect(&:name)
347
- Bullet::Association.check_unused_preload_associations
348
- Bullet::Association.should be_has_unused_preload_associations
349
- end
350
-
351
- it "should detect unused preload with category => entries, but no category => posts" do
352
- Category.includes([:posts, :entries]).each do |category|
353
- category.posts.collect(&:name)
354
- end
355
- Bullet::Association.check_unused_preload_associations
356
- Bullet::Association.should be_has_unused_preload_associations
357
- end
358
-
359
- it "should detect no unused preload" do
360
- Category.all.each do |category|
361
- category.posts.collect(&:name)
362
- category.entries.collect(&:name)
363
- end
364
- Bullet::Association.check_unused_preload_associations
365
- Bullet::Association.should_not be_has_unused_preload_associations
366
- end
367
- # end
368
-
369
- # FIXME: setup and teardown are not inherited by context
370
- # context "no preload" do
371
- it "should no preload only display only one post => comment" do
372
- Post.includes(:comments).each do |post|
373
- post.comments.first.name
374
- end
375
- Bullet::Association.should_not be_has_unpreload_associations
376
- end
377
-
378
- it "should no preload only one post => commnets" do
379
- Post.first.comments.collect(&:name)
380
- Bullet::Association.should_not be_has_unpreload_associations
381
- end
382
- # end
383
-
384
- # FIXME: setup and teardown are not inherited by context
385
- # context "scope for_category_name" do
386
- it "should detect preload with post => category" do
387
- Post.in_category_name('first').all.each do |post|
388
- post.category.name
389
- end
390
- Bullet::Association.should_not be_has_unpreload_associations
391
- end
392
-
393
- it "should not be unused preload post => category" do
394
- Post.in_category_name('first').all.collect(&:name)
395
- Bullet::Association.should_not be_has_unpreload_associations
396
- Bullet::Association.check_unused_preload_associations
397
- Bullet::Association.should_not be_has_unused_preload_associations
398
- end
399
- # end
400
-
401
- # FIXME: setup and teardown are not inherited by context
402
- # context "scope preload_posts" do
403
- it "should no preload post => comments with scope" do
404
- Post.preload_posts.each do |post|
405
- post.comments.collect(&:name)
406
- end
407
- Bullet::Association.should_not be_has_unpreload_associations
408
- end
409
-
410
- it "should unused preload with scope" do
411
- Post.preload_posts.collect(&:name)
412
- Bullet::Association.should_not be_has_unpreload_associations
413
- Bullet::Association.check_unused_preload_associations
414
- Bullet::Association.should be_has_unused_preload_associations
415
- end
416
- # end
417
-
418
- # FIXME: setup and teardown are not inherited by context
419
- # context "no unused" do
420
- it "should no unused only display only one post => comment" do
421
- Post.includes(:comments).each do |post|
422
- i = 0
423
- post.comments.each do |comment|
424
- if i == 0
425
- comment.name
426
- else
427
- i += 1
428
- end
429
- end
430
- end
431
- Bullet::Association.check_unused_preload_associations
432
- Bullet::Association.should_not be_has_unused_preload_associations
433
- end
434
- # end
435
-
436
- # FIXME: setup and teardown are not inherited by context
437
- # context "belongs_to" do
438
- it "should preload comments => post" do
439
- Comment.all.each do |comment|
440
- comment.post.name
441
- end
442
- Bullet::Association.should be_has_unpreload_associations
443
- end
444
-
445
- it "should no preload comment => post" do
446
- Comment.first.post.name
447
- Bullet::Association.should_not be_has_unpreload_associations
448
- end
449
-
450
- it "should no preload comments => post" do
451
- Comment.includes(:post).each do |comment|
452
- comment.post.name
453
- end
454
- Bullet::Association.should_not be_has_unpreload_associations
455
- end
456
-
457
- it "should detect no unused preload comments => post" do
458
- Comment.all.collect(&:name)
459
- Bullet::Association.check_unused_preload_associations
460
- Bullet::Association.should_not be_has_unused_preload_associations
461
- end
462
-
463
- it "should detect unused preload comments => post" do
464
- Comment.includes(:post).collect(&:name)
465
- Bullet::Association.check_unused_preload_associations
466
- Bullet::Association.should be_has_unused_preload_associations
467
- end
468
-
469
- it "should dectect no unused preload comments => post" do
470
- Comment.all.each do |comment|
471
- comment.post.name
472
- end
473
- Bullet::Association.check_unused_preload_associations
474
- Bullet::Association.should_not be_has_unused_preload_associations
475
- end
476
-
477
- it "should dectect no unused preload comments => post" do
478
- Comment.includes(:post).each do |comment|
479
- comment.post.name
480
- end
481
- Bullet::Association.check_unused_preload_associations
482
- Bullet::Association.should_not be_has_unused_preload_associations
483
- end
484
- # end
485
- end
486
-
487
- describe Bullet::Association, 'has_and_belongs_to_many' do
488
-
489
- def setup_db
490
- ActiveRecord::Schema.define(:version => 1) do
491
- create_table :students do |t|
492
- t.column :name, :string
493
- end
494
-
495
- create_table :teachers do |t|
496
- t.column :name, :string
497
- end
498
-
499
- create_table :students_teachers, :id => false do |t|
500
- t.column :student_id, :integer
501
- t.column :teacher_id, :integer
502
- end
503
- end
504
- end
505
-
506
- def teardown_db
507
- ActiveRecord::Base.connection.tables.each do |table|
508
- ActiveRecord::Base.connection.drop_table(table)
509
- end
510
- end
511
-
512
- class Student < ActiveRecord::Base
513
- has_and_belongs_to_many :teachers
514
- end
515
-
516
- class Teacher < ActiveRecord::Base
517
- has_and_belongs_to_many :students
518
- end
519
-
520
- before(:all) do
521
- setup_db
522
- student1 = Student.create(:name => 'first')
523
- student2 = Student.create(:name => 'second')
524
- teacher1 = Teacher.create(:name => 'first')
525
- teacher2 = Teacher.create(:name => 'second')
526
- student1.teachers = [teacher1, teacher2]
527
- student2.teachers = [teacher1, teacher2]
528
- teacher1.students << student1
529
- teacher2.students << student2
530
- end
531
-
532
- after(:all) do
533
- teardown_db
534
- end
535
-
536
- before(:each) do
537
- Bullet::Association.start_request
538
- end
539
-
540
- after(:each) do
541
- Bullet::Association.end_request
542
- end
543
-
544
- it "should detect unpreload associations" do
545
- Student.all.each do |student|
546
- student.teachers.collect(&:name)
547
- end
548
- Bullet::Association.should be_has_unpreload_associations
549
- end
550
-
551
- it "should detect no unpreload associations" do
552
- Student.includes(:teachers).each do |student|
553
- student.teachers.collect(&:name)
554
- end
555
- Bullet::Association.should_not be_has_unpreload_associations
556
- end
557
-
558
- it "should detect unused preload associations" do
559
- Student.includes(:teachers).collect(&:name)
560
- Bullet::Association.check_unused_preload_associations
561
- Bullet::Association.should be_has_unused_preload_associations
562
- end
563
-
564
- it "should detect no unused preload associations" do
565
- Student.all.collect(&:name)
566
- Bullet::Association.check_unused_preload_associations
567
- Bullet::Association.should_not be_has_unused_preload_associations
568
- end
569
- end
570
-
571
- describe Bullet::Association, 'has_many :through' do
572
-
573
- def setup_db
574
- ActiveRecord::Schema.define(:version => 1) do
575
- create_table :firms do |t|
576
- t.column :name, :string
577
- end
578
-
579
- create_table :clients do |t|
580
- t.column :name, :string
581
- end
582
-
583
- create_table :relationships do |t|
584
- t.column :firm_id, :integer
585
- t.column :client_id, :integer
586
- end
587
- end
588
- end
589
-
590
- def teardown_db
591
- ActiveRecord::Base.connection.tables.each do |table|
592
- ActiveRecord::Base.connection.drop_table(table)
593
- end
594
- end
595
-
596
- class Firm < ActiveRecord::Base
597
- has_many :relationships
598
- has_many :clients, :through => :relationships
599
- end
600
-
601
- class Client < ActiveRecord::Base
602
- has_many :relationships
603
- has_many :firms, :through => :relationships
604
- end
605
-
606
- class Relationship < ActiveRecord::Base
607
- belongs_to :firm
608
- belongs_to :client
609
- end
610
-
611
- before(:all) do
612
- setup_db
613
- firm1 = Firm.create(:name => 'first')
614
- firm2 = Firm.create(:name => 'second')
615
- client1 = Client.create(:name => 'first')
616
- client2 = Client.create(:name => 'second')
617
- firm1.clients = [client1, client2]
618
- firm2.clients = [client1, client2]
619
- client1.firms << firm1
620
- client2.firms << firm2
621
- end
622
-
623
- after(:all) do
624
- teardown_db
625
- end
626
-
627
- before(:each) do
628
- Bullet::Association.start_request
629
- end
630
-
631
- after(:each) do
632
- Bullet::Association.end_request
633
- end
634
-
635
- it "should detect unpreload associations" do
636
- Firm.all.each do |firm|
637
- firm.clients.collect(&:name)
638
- end
639
- Bullet::Association.should be_has_unpreload_associations
640
- end
641
-
642
- it "should detect no unpreload associations" do
643
- Firm.includes(:clients).each do |firm|
644
- firm.clients.collect(&:name)
645
- end
646
- Bullet::Association.should_not be_has_unpreload_associations
647
- end
648
-
649
- it "should detect no unused preload associations" do
650
- Firm.all.collect(&:name)
651
- Bullet::Association.check_unused_preload_associations
652
- Bullet::Association.should_not be_has_unused_preload_associations
653
- end
654
-
655
- it "should detect unused preload associations" do
656
- Firm.includes(:clients).collect(&:name)
657
- Bullet::Association.check_unused_preload_associations
658
- Bullet::Association.should be_has_unused_preload_associations
659
- end
660
- end
661
-
662
- describe Bullet::Association, 'has_many :as' do
663
-
664
- def setup_db
665
- ActiveRecord::Schema.define(:version => 1) do
666
- create_table :votes do |t|
667
- t.column :vote, :integer
668
- t.references :voteable, :polymorphic => true
669
- end
670
-
671
- create_table :users do |t|
672
- t.column :name, :string
673
- end
674
-
675
- create_table :pets do |t|
676
- t.column :name, :string
677
- t.column :user_id, :integer
678
- end
679
-
680
- create_table :news do |t|
681
- t.column :name, :string
682
- end
683
- end
684
- end
685
-
686
- def teardown_db
687
- ActiveRecord::Base.connection.tables.each do |table|
688
- ActiveRecord::Base.connection.drop_table(table)
689
- end
690
- end
691
-
692
- class Vote < ActiveRecord::Base
693
- belongs_to :voteable, :polymorphic => true
694
- end
695
-
696
- class User < ActiveRecord::Base
697
- has_many :votes, :as => :voteable
698
- has_many :pets
699
- end
700
-
701
- class Pet < ActiveRecord::Base
702
- belongs_to :user
703
- end
704
-
705
- class News < ActiveRecord::Base
706
- has_many :votes, :as => :voteable
707
- end
708
-
709
- before(:all) do
710
- setup_db
711
- user1 = User.create(:name => 'first')
712
- user2 = User.create(:name => 'second')
713
- user3 = User.create(:name => 'third')
714
- user4 = User.create(:name => 'fourth')
715
-
716
- pet1 = user1.pets.create(:name => "dog")
717
- pet2 = user1.pets.create(:name => "dog")
718
- pet3 = user2.pets.create(:name => "cat")
719
- pet4 = user2.pets.create(:name => "cat")
720
-
721
- user1.votes.create(:vote => 10)
722
- user1.votes.create(:vote => 20)
723
- user2.votes.create(:vote => 10)
724
- user2.votes.create(:vote => 20)
725
- user3.votes.create(:vote => 10)
726
- user3.votes.create(:vote => 20)
727
- user4.votes.create(:vote => 10)
728
- user4.votes.create(:vote => 20)
729
-
730
- news1 = News.create(:name => 'first')
731
- news2 = News.create(:name => 'second')
732
- news1.votes.create(:vote => 10)
733
- news1.votes.create(:vote => 20)
734
- news2.votes.create(:vote => 10)
735
- news2.votes.create(:vote => 20)
736
- end
737
-
738
- after(:all) do
739
- teardown_db
740
- end
741
-
742
- before(:each) do
743
- Bullet::Association.start_request
744
- end
745
-
746
- after(:each) do
747
- Bullet::Association.end_request
748
- end
749
-
750
- # this happens only when a polymorphic association is included along with another table which is being referenced in the query
751
- it "should not have unused preloaded associations with conditions" do
752
- all_users = User.includes(:pets)
753
- users_with_ten_votes = User.includes(:votes).where(["votes.vote = ?", 10])
754
- users_without_ten_votes = User.where(["users.id not in (?)", users_with_ten_votes.collect(&:id)])
755
- puts all_users.to_sql
756
- all_users.each { |t| t.pets.collect(&:name) }
757
- Bullet::Association.check_unused_preload_associations
758
- Bullet::Association.should_not be_unused_preload_associations_for(User, :pets)
759
- Bullet::Association.should_not be_unused_preload_associations_for(User, :votes)
760
- end
761
-
762
- it "should detect unpreload associations" do
763
- User.all.each do |user|
764
- user.votes.collect(&:vote)
765
- end
766
- Bullet::Association.should be_has_unpreload_associations
767
- end
768
-
769
- it "should detect no unpreload associations" do
770
- User.includes(:votes).each do |user|
771
- user.votes.collect(&:vote)
772
- end
773
- Bullet::Association.should_not be_has_unpreload_associations
774
- end
775
-
776
- it "should detect unpreload associations with voteable" do
777
- Vote.all.each do |vote|
778
- vote.voteable.name
779
- end
780
- Bullet::Association.should be_has_unpreload_associations
781
- end
782
-
783
- it "should detect no unpreload associations with voteable" do
784
- Vote.includes(:voteable).each do |vote|
785
- vote.voteable.name
786
- end
787
- Bullet::Association.should_not be_has_unpreload_associations
788
- end
789
-
790
- it "should detect no unused preload associations" do
791
- User.all.collect(&:name)
792
- Bullet::Association.check_unused_preload_associations
793
- Bullet::Association.should_not be_has_unused_preload_associations
794
- end
795
-
796
- it "should detect unused preload associations" do
797
- User.includes(:votes).collect(&:name)
798
- Bullet::Association.check_unused_preload_associations
799
- Bullet::Association.should be_has_unused_preload_associations
800
- end
801
-
802
- it "should detect no unused preload associations with voteable" do
803
- Vote.all.collect(&:vote)
804
- Bullet::Association.check_unused_preload_associations
805
- Bullet::Association.should_not be_has_unused_preload_associations
806
- end
807
-
808
- it "should detect unused preload associations with voteable" do
809
- Vote.includes(:voteable).collect(&:vote)
810
- Bullet::Association.check_unused_preload_associations
811
- Bullet::Association.should be_has_unused_preload_associations
812
- end
813
- end
814
-
815
- describe Bullet::Association, "has_one" do
816
-
817
- def setup_db
818
- ActiveRecord::Schema.define(:version => 1) do
819
- create_table :companies do |t|
820
- t.column :name, :string
821
- end
822
-
823
- create_table :addresses do |t|
824
- t.column :name, :string
825
- t.column :company_id, :integer
826
- end
827
- end
828
- end
829
-
830
- def teardown_db
831
- ActiveRecord::Base.connection.tables.each do |table|
832
- ActiveRecord::Base.connection.drop_table(table)
833
- end
834
- end
835
-
836
- class Company < ActiveRecord::Base
837
- has_one :address
838
- end
839
-
840
- class Address < ActiveRecord::Base
841
- belongs_to :company
842
- end
843
-
844
- before(:all) do
845
- setup_db
846
-
847
- company1 = Company.create(:name => 'first')
848
- company2 = Company.create(:name => 'second')
849
-
850
- Address.create(:name => 'first', :company => company1)
851
- Address.create(:name => 'second', :company => company2)
852
- end
853
-
854
- after(:all) do
855
- teardown_db
856
- end
857
-
858
- before(:each) do
859
- Bullet::Association.start_request
860
- end
861
-
862
- after(:each) do
863
- Bullet::Association.end_request
864
- end
865
-
866
- it "should detect unpreload association" do
867
- Company.all.each do |company|
868
- company.address.name
869
- end
870
- Bullet::Association.should be_has_unpreload_associations
871
- end
872
-
873
- it "should detect no unpreload association" do
874
- Company.find(:all, :include => :address).each do |company|
875
- company.address.name
876
- end
877
- Bullet::Association.should_not be_has_unpreload_associations
878
- end
879
-
880
- it "should detect no unused preload association" do
881
- Company.all.collect(&:name)
882
- Bullet::Association.check_unused_preload_associations
883
- Bullet::Association.should_not be_has_unused_preload_associations
884
- end
885
-
886
- it "should detect unused preload association" do
887
- Company.find(:all, :include => :address).collect(&:name)
888
- Bullet::Association.check_unused_preload_associations
889
- Bullet::Association.should be_has_unused_preload_associations
890
- end
891
- end
892
-
893
- describe Bullet::Association, "call one association that in possible objects" do
894
-
895
- def setup_db
896
- ActiveRecord::Schema.define(:version => 1) do
897
- create_table :contacts do |t|
898
- t.column :name, :string
899
- end
900
-
901
- create_table :emails do |t|
902
- t.column :name, :string
903
- t.column :contact_id, :integer
904
- end
905
- end
906
- end
907
-
908
- def teardown_db
909
- ActiveRecord::Base.connection.tables.each do |table|
910
- ActiveRecord::Base.connection.drop_table(table)
911
- end
912
- end
913
-
914
- class Contact < ActiveRecord::Base
915
- has_many :emails
916
- end
917
-
918
- class Email < ActiveRecord::Base
919
- belongs_to :contact
920
- end
921
-
922
- before(:all) do
923
- setup_db
924
-
925
- contact1 = Contact.create(:name => 'first')
926
- contact2 = Contact.create(:name => 'second')
927
-
928
- email1 = contact1.emails.create(:name => 'first')
929
- email2 = contact1.emails.create(:name => 'second')
930
- email3 = contact2.emails.create(:name => 'third')
931
- email4 = contact2.emails.create(:name => 'fourth')
932
- end
933
-
934
- after(:all) do
935
- teardown_db
936
- end
937
-
938
- before(:each) do
939
- Bullet::Association.start_request
940
- end
941
-
942
- after(:each) do
943
- Bullet::Association.end_request
944
- end
945
-
946
- it "should detect no unpreload association" do
947
- Contact.all
948
- Contact.first.emails.collect(&:name)
949
- Bullet::Association.should_not be_has_unpreload_associations
950
- end
951
- end
952
-
953
- describe Bullet::Association, "STI" do
954
-
955
- def setup_db
956
- ActiveRecord::Schema.define(:version => 1) do
957
- create_table :documents do |t|
958
- t.string :name
959
- t.string :type
960
- t.integer :parent_id
961
- t.integer :author_id
962
- end
963
-
964
- create_table :authors do |t|
965
- t.string :name
966
- end
967
- end
968
- end
969
-
970
- def teardown_db
971
- ActiveRecord::Base.connection.tables.each do |table|
972
- ActiveRecord::Base.connection.drop_table(table)
973
- end
974
- end
975
-
976
- class Document < ActiveRecord::Base
977
- has_many :children, :class_name => "Document", :foreign_key => 'parent_id'
978
- belongs_to :parent, :class_name => "Document", :foreign_key => 'parent_id'
979
- belongs_to :author
980
- end
981
-
982
- class Page < Document
983
- end
984
-
985
- class Folder < Document
986
- end
987
-
988
- class Author < ActiveRecord::Base
989
- has_many :documents
990
- end
991
-
992
- before(:all) do
993
- setup_db
994
- author1 = Author.create(:name => 'author1')
995
- author2 = Author.create(:name => 'author2')
996
- folder1 = Folder.create(:name => 'folder1', :author_id => author1.id)
997
- folder2 = Folder.create(:name => 'folder2', :author_id => author2.id)
998
- page1 = Page.create(:name => 'page1', :parent_id => folder1.id, :author_id => author1.id)
999
- page2 = Page.create(:name => 'page2', :parent_id => folder1.id, :author_id => author1.id)
1000
- page3 = Page.create(:name => 'page3', :parent_id => folder2.id, :author_id => author2.id)
1001
- page4 = Page.create(:name => 'page4', :parent_id => folder2.id, :author_id => author2.id)
1002
- end
1003
-
1004
- before(:each) do
1005
- Bullet::Association.start_request
1006
- end
1007
-
1008
- after(:each) do
1009
- Bullet::Association.end_request
1010
- end
1011
-
1012
- it "should detect unpreload associations" do
1013
- Page.all.each do |page|
1014
- page.author.name
1015
- end
1016
- Bullet::Association.should be_has_unpreload_associations
1017
- Bullet::Association.check_unused_preload_associations
1018
- Bullet::Association.should_not be_has_unused_preload_associations
1019
- end
1020
-
1021
- it "should not detect unpreload associations" do
1022
- Page.find(:all, :include => :author).each do |page|
1023
- page.author.name
1024
- end
1025
- Bullet::Association.should_not be_has_unpreload_associations
1026
- Bullet::Association.check_unused_preload_associations
1027
- Bullet::Association.should_not be_has_unused_preload_associations
1028
- end
1029
-
1030
- it "should detect unused preload associations" do
1031
- Page.find(:all, :include => :author).collect(&:name)
1032
- Bullet::Association.should_not be_has_unpreload_associations
1033
- Bullet::Association.check_unused_preload_associations
1034
- Bullet::Association.should be_has_unused_preload_associations
1035
- end
1036
-
1037
- it "should not detect unused preload associations" do
1038
- Page.all.collect(&:name)
1039
- Bullet::Association.should_not be_has_unpreload_associations
1040
- Bullet::Association.check_unused_preload_associations
1041
- Bullet::Association.should_not be_has_unused_preload_associations
1042
- end
1043
- end