bullet 1.7.6 → 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +17 -30
- data/README_for_rails2.textile +404 -0
- data/Rakefile +6 -5
- data/VERSION +1 -1
- data/bullet.gemspec +9 -6
- data/lib/bullet.rb +12 -5
- data/lib/bullet/{action_controller.rb → action_controller2.rb} +2 -1
- data/lib/bullet/{active_record.rb → active_record2.rb} +2 -1
- data/lib/bullet/active_record3.rb +113 -0
- data/lib/bullet/association.rb +2 -2
- data/lib/bullet/logger.rb +1 -1
- data/spec/bullet/association_for_chris_spec.rb +4 -4
- data/spec/bullet/association_for_peschkaj_spec.rb +1 -1
- data/spec/bullet/association_spec.rb +117 -109
- data/spec/bullet/counter_spec.rb +1 -1
- data/spec/spec.opts +0 -5
- data/spec/spec_helper.rb +7 -5
- metadata +22 -8
data/Rakefile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rake'
|
2
|
-
require '
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
require 'rake/rdoctask'
|
4
4
|
require 'jeweler'
|
5
5
|
|
@@ -15,10 +15,11 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
15
15
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
# FIXME: 'rake spec' will break the test, just run 'ruby spec/association_spec.rb'
|
19
|
+
#desc "Run all specs in spec directory"
|
20
|
+
#Rspec::Core::RakeTask.new(:spec) do |t|
|
21
|
+
#t.pattern = FileList['spec/**/*_spec.rb']
|
22
|
+
#end
|
22
23
|
|
23
24
|
Jeweler::Tasks.new do |gemspec|
|
24
25
|
gemspec.name = "bullet"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0.beta.1
|
data/bullet.gemspec
CHANGED
@@ -5,25 +5,28 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bullet}
|
8
|
-
s.version = "
|
8
|
+
s.version = "2.0.0.beta.1"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Richard Huang"]
|
12
12
|
s.date = %q{2010-03-07}
|
13
13
|
s.description = %q{The Bullet plugin is designed to help you increase your application's performance by reducing the number of queries it makes. It will watch your queries while you develop your application and notify you when you should add eager loading (N+1 queries) or when you're using eager loading that isn't necessary.}
|
14
14
|
s.email = %q{flyerhzm@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
|
-
"README.textile"
|
16
|
+
"README.textile",
|
17
|
+
"README_for_rails2.textile"
|
17
18
|
]
|
18
19
|
s.files = [
|
19
20
|
"MIT-LICENSE",
|
20
21
|
"README.textile",
|
22
|
+
"README_for_rails2.textile",
|
21
23
|
"Rakefile",
|
22
24
|
"VERSION",
|
23
25
|
"bullet.gemspec",
|
24
26
|
"lib/bullet.rb",
|
25
|
-
"lib/bullet/
|
26
|
-
"lib/bullet/
|
27
|
+
"lib/bullet/action_controller2.rb",
|
28
|
+
"lib/bullet/active_record2.rb",
|
29
|
+
"lib/bullet/active_record3.rb",
|
27
30
|
"lib/bullet/association.rb",
|
28
31
|
"lib/bullet/counter.rb",
|
29
32
|
"lib/bullet/logger.rb",
|
@@ -41,7 +44,7 @@ Gem::Specification.new do |s|
|
|
41
44
|
s.homepage = %q{http://github.com/flyerhzm/bullet}
|
42
45
|
s.rdoc_options = ["--charset=UTF-8"]
|
43
46
|
s.require_paths = ["lib"]
|
44
|
-
s.rubygems_version = %q{1.3.
|
47
|
+
s.rubygems_version = %q{1.3.6}
|
45
48
|
s.summary = %q{A plugin to kill N+1 queries and unused eager loading}
|
46
49
|
s.test_files = [
|
47
50
|
"spec/spec_helper.rb",
|
data/lib/bullet.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
-
require 'action_controller/dispatcher'
|
2
1
|
require 'bulletware'
|
3
2
|
|
4
3
|
module Bullet
|
5
|
-
|
6
|
-
|
4
|
+
if Rails.version =~ /^3.0/
|
5
|
+
autoload :ActiveRecord, 'bullet/active_record3'
|
6
|
+
else
|
7
|
+
autoload :ActiveRecord, 'bullet/active_record2'
|
8
|
+
autoload :ActionController, 'bullet/action_controller2'
|
9
|
+
end
|
7
10
|
autoload :Association, 'bullet/association'
|
8
11
|
autoload :Counter, 'bullet/counter'
|
9
12
|
autoload :BulletLogger, 'bullet/logger'
|
@@ -16,8 +19,12 @@ module Bullet
|
|
16
19
|
@enable = enable
|
17
20
|
if enable?
|
18
21
|
Bullet::ActiveRecord.enable
|
19
|
-
|
20
|
-
|
22
|
+
if Rails.version =~ /^3.0/
|
23
|
+
require 'action_controller/metal'
|
24
|
+
::ActionController::Metal.middleware_stack.use Bulletware
|
25
|
+
elsif Rails.version =~/^2.3/
|
26
|
+
Bullet::ActionController.enable
|
27
|
+
require 'action_controller/dispatcher'
|
21
28
|
::ActionController::Dispatcher.middleware.use Bulletware
|
22
29
|
end
|
23
30
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Bullet
|
2
2
|
module ActiveRecord
|
3
3
|
def self.enable
|
4
|
+
require 'active_record'
|
4
5
|
::ActiveRecord::Base.class_eval do
|
5
6
|
class << self
|
6
7
|
alias_method :origin_find_every, :find_every
|
@@ -94,7 +95,7 @@ module Bullet
|
|
94
95
|
result
|
95
96
|
end
|
96
97
|
end
|
97
|
-
|
98
|
+
|
98
99
|
::ActiveRecord::Associations::HasManyThroughAssociation.class_eval do
|
99
100
|
alias_method :origin_has_cached_counter?, :has_cached_counter?
|
100
101
|
def has_cached_counter?
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Bullet
|
2
|
+
module ActiveRecord
|
3
|
+
def self.enable
|
4
|
+
require 'active_record'
|
5
|
+
::ActiveRecord::Relation.class_eval do
|
6
|
+
alias_method :origin_to_a, :to_a
|
7
|
+
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
8
|
+
# if select only one object, then the only one object has impossible to cause N+1 query.
|
9
|
+
def to_a
|
10
|
+
records = origin_to_a
|
11
|
+
if records.size > 1
|
12
|
+
Bullet::Association.add_possible_objects(records)
|
13
|
+
Bullet::Counter.add_possible_objects(records)
|
14
|
+
elsif records.size == 1
|
15
|
+
Bullet::Association.add_impossible_object(records.first)
|
16
|
+
Bullet::Counter.add_impossible_object(records.first)
|
17
|
+
end
|
18
|
+
records
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
::ActiveRecord::AssociationPreload::ClassMethods.class_eval do
|
23
|
+
alias_method :origin_preload_associations, :preload_associations
|
24
|
+
# include query for one to many associations.
|
25
|
+
# keep this eager loadings.
|
26
|
+
def preload_associations(records, associations, preload_options={})
|
27
|
+
records = [records].flatten.compact.uniq
|
28
|
+
return if records.empty?
|
29
|
+
records.each do |record|
|
30
|
+
Bullet::Association.add_object_associations(record, associations)
|
31
|
+
end
|
32
|
+
Bullet::Association.add_eager_loadings(records, associations)
|
33
|
+
origin_preload_associations(records, associations, preload_options={})
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
::ActiveRecord::FinderMethods.class_eval do
|
38
|
+
# add includes in scope
|
39
|
+
alias_method :origin_find_with_associations, :find_with_associations
|
40
|
+
def find_with_associations
|
41
|
+
records = origin_find_with_associations
|
42
|
+
associations = (@eager_load_values + @includes_values).uniq
|
43
|
+
records.each do |record|
|
44
|
+
Bullet::Association.add_object_associations(record, associations)
|
45
|
+
Bullet::Association.call_association(record, associations)
|
46
|
+
end
|
47
|
+
Bullet::Association.add_eager_loadings(records, associations)
|
48
|
+
records
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
::ActiveRecord::Associations::ClassMethods::JoinDependency.class_eval do
|
53
|
+
alias_method :origin_construct_association, :construct_association
|
54
|
+
# call join associations
|
55
|
+
def construct_association(record, join, row)
|
56
|
+
associations = join.reflection.name
|
57
|
+
Bullet::Association.add_object_associations(record, associations)
|
58
|
+
Bullet::Association.call_association(record, associations)
|
59
|
+
origin_construct_association(record, join, row)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
::ActiveRecord::Associations::AssociationCollection.class_eval do
|
64
|
+
# call one to many associations
|
65
|
+
alias_method :origin_load_target, :load_target
|
66
|
+
def load_target
|
67
|
+
Bullet::Association.call_association(@owner, @reflection.name)
|
68
|
+
origin_load_target
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
::ActiveRecord::Associations::AssociationProxy.class_eval do
|
73
|
+
# call has_one and belong_to association
|
74
|
+
alias_method :origin_load_target, :load_target
|
75
|
+
def load_target
|
76
|
+
# avoid stack level too deep
|
77
|
+
result = origin_load_target
|
78
|
+
Bullet::Association.call_association(@owner, @reflection.name) unless caller.to_s.include? 'load_target'
|
79
|
+
Bullet::Association.add_possible_objects(result)
|
80
|
+
result
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
::ActiveRecord::Associations::HasManyAssociation.class_eval do
|
85
|
+
alias_method :origin_has_cached_counter?, :has_cached_counter?
|
86
|
+
|
87
|
+
def has_cached_counter?
|
88
|
+
result = origin_has_cached_counter?
|
89
|
+
Bullet::Counter.add_counter_cache(@owner, @reflection.name) unless result
|
90
|
+
result
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
::ActiveRecord::Associations::HasManyThroughAssociation.class_eval do
|
95
|
+
alias_method :origin_has_cached_counter?, :has_cached_counter?
|
96
|
+
def has_cached_counter?
|
97
|
+
result = origin_has_cached_counter?
|
98
|
+
Bullet::Counter.add_counter_cache(@owner, @reflection.name) unless result
|
99
|
+
result
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
::ActiveRecord::Associations::HasManyThroughAssociation.class_eval do
|
104
|
+
alias_method :origin_has_cached_counter?, :has_cached_counter?
|
105
|
+
def has_cached_counter?
|
106
|
+
result = origin_has_cached_counter?
|
107
|
+
Bullet::Counter.add_counter_cache(@owner, @reflection.name) unless result
|
108
|
+
result
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/bullet/association.rb
CHANGED
@@ -280,9 +280,9 @@ module Bullet
|
|
280
280
|
@@eager_loadings ||= {}
|
281
281
|
end
|
282
282
|
|
283
|
-
VENDOR_ROOT = File.join(
|
283
|
+
VENDOR_ROOT = File.join(Rails.root, 'vendor')
|
284
284
|
def caller_in_project
|
285
|
-
callers << caller.select {|c| c =~ /#{
|
285
|
+
callers << caller.select {|c| c =~ /#{Rails.root}/}.reject {|c| c =~ /#{VENDOR_ROOT}/}
|
286
286
|
callers.uniq!
|
287
287
|
end
|
288
288
|
|
data/lib/bullet/logger.rb
CHANGED
@@ -73,24 +73,24 @@ describe Bullet::Association do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
it "should detect unpreload association from deal to hotel" do
|
76
|
-
Deal.
|
76
|
+
Deal.all.each do |deal|
|
77
77
|
deal.hotel.location.name
|
78
78
|
end
|
79
79
|
Bullet::Association.should be_detecting_unpreloaded_association_for(Deal, :hotel)
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should detect unpreload association from hotel to location" do
|
83
|
-
Deal.
|
83
|
+
Deal.includes(:hotel).each do |deal|
|
84
84
|
deal.hotel.location.name
|
85
85
|
end
|
86
86
|
Bullet::Association.should be_detecting_unpreloaded_association_for(Hotel, :location)
|
87
87
|
end
|
88
88
|
|
89
89
|
it "should not detect unpreload association" do
|
90
|
-
Deal.
|
90
|
+
Deal.includes({:hotel => :location}).each do |deal|
|
91
91
|
deal.hotel.location.name
|
92
92
|
end
|
93
93
|
Bullet::Association.should_not be_has_unused_preload_associations
|
94
94
|
end
|
95
95
|
end
|
96
|
-
end
|
96
|
+
end
|
@@ -73,7 +73,7 @@ describe Bullet::Association do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
it "should not detect unused preload associations" do
|
76
|
-
category = Category.
|
76
|
+
category = Category.includes({:submissions => :user}).order("id DESC").find_by_name('category1')
|
77
77
|
category.submissions.map do |submission|
|
78
78
|
submission.name
|
79
79
|
submission.user.name
|
@@ -55,9 +55,9 @@ describe Bullet::Association, 'has_many' do
|
|
55
55
|
belongs_to :writer
|
56
56
|
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
scope :preload_posts, lambda { includes(:comments) }
|
59
|
+
scope :in_category_name, lambda { |name|
|
60
|
+
where(['categories.name = ?', name]).includes(:category)
|
61
61
|
}
|
62
62
|
end
|
63
63
|
|
@@ -128,49 +128,50 @@ describe Bullet::Association, 'has_many' do
|
|
128
128
|
Bullet::Association.end_request
|
129
129
|
end
|
130
130
|
|
131
|
-
|
131
|
+
# FIXME: setup and teardown are not inherited by context
|
132
|
+
# context "for unused cases" do
|
132
133
|
#If you have the same record created twice with different includes
|
133
134
|
# the hash value get's accumulated includes, which leads to false Unused eager loading
|
134
|
-
it "should not incorrectly mark associations as unused when multiple object instances" do
|
135
|
-
comments_with_author = Comment.
|
136
|
-
comments_with_post = Comment.
|
137
|
-
comments_with_author.each { |c| c.author.name }
|
138
|
-
comments_with_author.each { |c| c.post.name }
|
139
|
-
Bullet::Association.check_unused_preload_associations
|
140
|
-
Bullet::Association.should be_unused_preload_associations_for(Comment, :post)
|
141
|
-
Bullet::Association.should be_detecting_unpreloaded_association_for(Comment, :post)
|
142
|
-
end
|
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
|
143
144
|
|
144
145
|
# same as above with different Models being queried
|
145
|
-
it "should not incorrectly mark associations as unused when multiple object instances different Model" do
|
146
|
-
post_with_comments = Post.
|
147
|
-
comments_with_author = Comment.
|
148
|
-
post_with_comments.each { |p| p.comments.first.author.name }
|
149
|
-
comments_with_author.each { |c| c.name }
|
150
|
-
Bullet::Association.check_unused_preload_associations
|
151
|
-
Bullet::Association.should be_unused_preload_associations_for(Comment, :author)
|
152
|
-
Bullet::Association.should be_detecting_unpreloaded_association_for(Comment, :author)
|
153
|
-
end
|
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
|
154
155
|
|
155
156
|
# this test passes right now. But is a regression test to ensure that if only a small set of returned records
|
156
157
|
# is not used that a unused preload association error is not generated
|
157
158
|
it "should not have unused when small set of returned records are discarded" do
|
158
|
-
comments_with_author = Comment.
|
159
|
-
comment_collection = comments_with_author.
|
159
|
+
comments_with_author = Comment.includes(:author)
|
160
|
+
comment_collection = comments_with_author.limit(2)
|
160
161
|
comment_collection.collect { |com| com.author.name }
|
161
162
|
Bullet::Association.check_unused_preload_associations
|
162
163
|
Bullet::Association.should_not be_unused_preload_associations_for(Comment, :author)
|
163
164
|
end
|
164
|
-
end
|
165
|
+
# end
|
165
166
|
|
166
167
|
|
167
|
-
|
168
|
+
# FIXME: setup and teardown are not inherited by context
|
169
|
+
# context "comments => posts => category" do
|
168
170
|
|
169
171
|
# this happens because the post isn't a possible object even though the writer is access through the post
|
170
172
|
# which leads to an 1+N queries
|
171
173
|
it "should detect unpreloaded writer" do
|
172
|
-
Comment.
|
173
|
-
:conditions => ["base_users.id = ?", BaseUser.first]).each do |com|
|
174
|
+
Comment.includes([:author, :post]).where(["base_users.id = ?", BaseUser.first]).each do |com|
|
174
175
|
com.post.writer.name
|
175
176
|
end
|
176
177
|
Bullet::Association.should be_detecting_unpreloaded_association_for(Post, :writer)
|
@@ -179,8 +180,7 @@ describe Bullet::Association, 'has_many' do
|
|
179
180
|
# this happens because the comment doesn't break down the hash into keys
|
180
181
|
# properly creating an association from comment to post
|
181
182
|
it "should detect preload of comment => post" do
|
182
|
-
comments = Comment.
|
183
|
-
:conditions => ["base_users.id = ?", BaseUser.first]).each do |com|
|
183
|
+
comments = Comment.includes([:author, {:post => :writer}]).where(["base_users.id = ?", BaseUser.first]).each do |com|
|
184
184
|
com.post.writer.name
|
185
185
|
end
|
186
186
|
Bullet::Association.should_not be_detecting_unpreloaded_association_for(Comment, :post)
|
@@ -188,8 +188,7 @@ describe Bullet::Association, 'has_many' do
|
|
188
188
|
end
|
189
189
|
|
190
190
|
it "should detect preload of post => writer" do
|
191
|
-
comments = Comment.
|
192
|
-
:conditions => ["base_users.id = ?", BaseUser.first]).each do |com|
|
191
|
+
comments = Comment.includes([:author, {:post => :writer}]).where(["base_users.id = ?", BaseUser.first]).each do |com|
|
193
192
|
com.post.writer.name
|
194
193
|
end
|
195
194
|
Bullet::Association.should be_creating_object_association_for(comments.first, :author)
|
@@ -210,42 +209,43 @@ describe Bullet::Association, 'has_many' do
|
|
210
209
|
# a repeating loop of calls in this test
|
211
210
|
it "should not raise a stack error from posts to category" do
|
212
211
|
lambda {
|
213
|
-
Comment.
|
212
|
+
Comment.includes({:post => :category}).each do |com|
|
214
213
|
com.post.category
|
215
214
|
end
|
216
215
|
}.should_not raise_error(SystemStackError)
|
217
216
|
end
|
218
|
-
end
|
217
|
+
# end
|
219
218
|
|
220
|
-
|
219
|
+
# FIXME: setup and teardown are not inherited by context
|
220
|
+
# context "post => comments" do
|
221
221
|
it "should detect preload with post => comments" do
|
222
|
-
Post.
|
222
|
+
Post.includes(:comments).each do |post|
|
223
223
|
post.comments.collect(&:name)
|
224
224
|
end
|
225
225
|
Bullet::Association.should_not be_has_unpreload_associations
|
226
226
|
end
|
227
227
|
|
228
228
|
it "should detect no preload post => comments" do
|
229
|
-
Post.
|
229
|
+
Post.all.each do |post|
|
230
230
|
post.comments.collect(&:name)
|
231
231
|
end
|
232
232
|
Bullet::Association.should be_has_unpreload_associations
|
233
233
|
end
|
234
234
|
|
235
235
|
it "should detect unused preload post => comments for post" do
|
236
|
-
Post.
|
236
|
+
Post.includes(:comments).collect(&:name)
|
237
237
|
Bullet::Association.check_unused_preload_associations
|
238
238
|
Bullet::Association.should be_has_unused_preload_associations
|
239
239
|
end
|
240
240
|
|
241
241
|
it "should detect no unused preload post => comments for post" do
|
242
|
-
Post.
|
242
|
+
Post.all.collect(&:name)
|
243
243
|
Bullet::Association.check_unused_preload_associations
|
244
244
|
Bullet::Association.should_not be_has_unused_preload_associations
|
245
245
|
end
|
246
246
|
|
247
247
|
it "should detect no unused preload post => comments for comment" do
|
248
|
-
Post.
|
248
|
+
Post.all.each do |post|
|
249
249
|
post.comments.collect(&:name)
|
250
250
|
end
|
251
251
|
Bullet::Association.check_unused_preload_associations
|
@@ -254,17 +254,18 @@ describe Bullet::Association, 'has_many' do
|
|
254
254
|
Bullet::Association.end_request
|
255
255
|
Bullet::Association.start_request
|
256
256
|
|
257
|
-
Post.
|
257
|
+
Post.all.each do |post|
|
258
258
|
post.comments.collect(&:name)
|
259
259
|
end
|
260
260
|
Bullet::Association.check_unused_preload_associations
|
261
261
|
Bullet::Association.should_not be_has_unused_preload_associations
|
262
262
|
end
|
263
|
-
end
|
263
|
+
# end
|
264
264
|
|
265
|
-
|
265
|
+
# FIXME: setup and teardown are not inherited by context
|
266
|
+
# context "category => posts => comments" do
|
266
267
|
it "should detect preload with category => posts => comments" do
|
267
|
-
Category.
|
268
|
+
Category.includes({:posts => :comments}).each do |category|
|
268
269
|
category.posts.each do |post|
|
269
270
|
post.comments.collect(&:name)
|
270
271
|
end
|
@@ -273,7 +274,7 @@ describe Bullet::Association, 'has_many' do
|
|
273
274
|
end
|
274
275
|
|
275
276
|
it "should detect preload category => posts, but no post => comments" do
|
276
|
-
Category.
|
277
|
+
Category.includes(:posts).each do |category|
|
277
278
|
category.posts.each do |post|
|
278
279
|
post.comments.collect(&:name)
|
279
280
|
end
|
@@ -282,7 +283,7 @@ describe Bullet::Association, 'has_many' do
|
|
282
283
|
end
|
283
284
|
|
284
285
|
it "should detect no preload category => posts => comments" do
|
285
|
-
Category.
|
286
|
+
Category.all.each do |category|
|
286
287
|
category.posts.each do |post|
|
287
288
|
post.comments.collect(&:name)
|
288
289
|
end
|
@@ -291,13 +292,13 @@ describe Bullet::Association, 'has_many' do
|
|
291
292
|
end
|
292
293
|
|
293
294
|
it "should detect unused preload with category => posts => comments" do
|
294
|
-
Category.
|
295
|
+
Category.includes({:posts => :comments}).collect(&:name)
|
295
296
|
Bullet::Association.check_unused_preload_associations
|
296
297
|
Bullet::Association.should be_has_unused_preload_associations
|
297
298
|
end
|
298
299
|
|
299
300
|
it "should detect unused preload with post => commnets, no category => posts" do
|
300
|
-
Category.
|
301
|
+
Category.includes({:posts => :comments}).each do |category|
|
301
302
|
category.posts.collect(&:name)
|
302
303
|
end
|
303
304
|
Bullet::Association.check_unused_preload_associations
|
@@ -305,7 +306,7 @@ describe Bullet::Association, 'has_many' do
|
|
305
306
|
end
|
306
307
|
|
307
308
|
it "should no detect preload with category => posts => comments" do
|
308
|
-
Category.
|
309
|
+
Category.all.each do |category|
|
309
310
|
category.posts.each do |post|
|
310
311
|
post.comments.collect(&:name)
|
311
312
|
end
|
@@ -313,11 +314,12 @@ describe Bullet::Association, 'has_many' do
|
|
313
314
|
Bullet::Association.check_unused_preload_associations
|
314
315
|
Bullet::Association.should_not be_has_unused_preload_associations
|
315
316
|
end
|
316
|
-
end
|
317
|
+
# end
|
317
318
|
|
318
|
-
|
319
|
+
# FIXME: setup and teardown are not inherited by context
|
320
|
+
# context "category => posts, category => entries" do
|
319
321
|
it "should detect preload with category => [posts, entries]" do
|
320
|
-
Category.
|
322
|
+
Category.includes([:posts, :entries]).each do |category|
|
321
323
|
category.posts.collect(&:name)
|
322
324
|
category.entries.collect(&:name)
|
323
325
|
end
|
@@ -325,7 +327,7 @@ describe Bullet::Association, 'has_many' do
|
|
325
327
|
end
|
326
328
|
|
327
329
|
it "should detect preload with category => posts, but no category => entries" do
|
328
|
-
Category.
|
330
|
+
Category.includes(:posts).each do |category|
|
329
331
|
category.posts.collect(&:name)
|
330
332
|
category.entries.collect(&:name)
|
331
333
|
end
|
@@ -333,7 +335,7 @@ describe Bullet::Association, 'has_many' do
|
|
333
335
|
end
|
334
336
|
|
335
337
|
it "should detect no preload with category => [posts, entries]" do
|
336
|
-
Category.
|
338
|
+
Category.all.each do |category|
|
337
339
|
category.posts.collect(&:name)
|
338
340
|
category.entries.collect(&:name)
|
339
341
|
end
|
@@ -341,13 +343,13 @@ describe Bullet::Association, 'has_many' do
|
|
341
343
|
end
|
342
344
|
|
343
345
|
it "should detect unused with category => [posts, entries]" do
|
344
|
-
Category.
|
346
|
+
Category.includes([:posts, :entries]).collect(&:name)
|
345
347
|
Bullet::Association.check_unused_preload_associations
|
346
348
|
Bullet::Association.should be_has_unused_preload_associations
|
347
349
|
end
|
348
350
|
|
349
351
|
it "should detect unused preload with category => entries, but no category => posts" do
|
350
|
-
Category.
|
352
|
+
Category.includes([:posts, :entries]).each do |category|
|
351
353
|
category.posts.collect(&:name)
|
352
354
|
end
|
353
355
|
Bullet::Association.check_unused_preload_associations
|
@@ -355,18 +357,19 @@ describe Bullet::Association, 'has_many' do
|
|
355
357
|
end
|
356
358
|
|
357
359
|
it "should detect no unused preload" do
|
358
|
-
Category.
|
360
|
+
Category.all.each do |category|
|
359
361
|
category.posts.collect(&:name)
|
360
362
|
category.entries.collect(&:name)
|
361
363
|
end
|
362
364
|
Bullet::Association.check_unused_preload_associations
|
363
365
|
Bullet::Association.should_not be_has_unused_preload_associations
|
364
366
|
end
|
365
|
-
end
|
367
|
+
# end
|
366
368
|
|
367
|
-
|
369
|
+
# FIXME: setup and teardown are not inherited by context
|
370
|
+
# context "no preload" do
|
368
371
|
it "should no preload only display only one post => comment" do
|
369
|
-
Post.
|
372
|
+
Post.includes(:comments).each do |post|
|
370
373
|
post.comments.first.name
|
371
374
|
end
|
372
375
|
Bullet::Association.should_not be_has_unpreload_associations
|
@@ -376,9 +379,10 @@ describe Bullet::Association, 'has_many' do
|
|
376
379
|
Post.first.comments.collect(&:name)
|
377
380
|
Bullet::Association.should_not be_has_unpreload_associations
|
378
381
|
end
|
379
|
-
end
|
382
|
+
# end
|
380
383
|
|
381
|
-
|
384
|
+
# FIXME: setup and teardown are not inherited by context
|
385
|
+
# context "scope for_category_name" do
|
382
386
|
it "should detect preload with post => category" do
|
383
387
|
Post.in_category_name('first').all.each do |post|
|
384
388
|
post.category.name
|
@@ -392,27 +396,29 @@ describe Bullet::Association, 'has_many' do
|
|
392
396
|
Bullet::Association.check_unused_preload_associations
|
393
397
|
Bullet::Association.should_not be_has_unused_preload_associations
|
394
398
|
end
|
395
|
-
end
|
399
|
+
# end
|
396
400
|
|
397
|
-
|
398
|
-
|
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
|
399
404
|
Post.preload_posts.each do |post|
|
400
405
|
post.comments.collect(&:name)
|
401
406
|
end
|
402
407
|
Bullet::Association.should_not be_has_unpreload_associations
|
403
408
|
end
|
404
409
|
|
405
|
-
it "should unused preload with
|
410
|
+
it "should unused preload with scope" do
|
406
411
|
Post.preload_posts.collect(&:name)
|
407
412
|
Bullet::Association.should_not be_has_unpreload_associations
|
408
413
|
Bullet::Association.check_unused_preload_associations
|
409
414
|
Bullet::Association.should be_has_unused_preload_associations
|
410
415
|
end
|
411
|
-
end
|
416
|
+
# end
|
412
417
|
|
413
|
-
|
418
|
+
# FIXME: setup and teardown are not inherited by context
|
419
|
+
# context "no unused" do
|
414
420
|
it "should no unused only display only one post => comment" do
|
415
|
-
Post.
|
421
|
+
Post.includes(:comments).each do |post|
|
416
422
|
i = 0
|
417
423
|
post.comments.each do |comment|
|
418
424
|
if i == 0
|
@@ -425,11 +431,12 @@ describe Bullet::Association, 'has_many' do
|
|
425
431
|
Bullet::Association.check_unused_preload_associations
|
426
432
|
Bullet::Association.should_not be_has_unused_preload_associations
|
427
433
|
end
|
428
|
-
end
|
434
|
+
# end
|
429
435
|
|
430
|
-
|
436
|
+
# FIXME: setup and teardown are not inherited by context
|
437
|
+
# context "belongs_to" do
|
431
438
|
it "should preload comments => post" do
|
432
|
-
Comment.
|
439
|
+
Comment.all.each do |comment|
|
433
440
|
comment.post.name
|
434
441
|
end
|
435
442
|
Bullet::Association.should be_has_unpreload_associations
|
@@ -441,26 +448,26 @@ describe Bullet::Association, 'has_many' do
|
|
441
448
|
end
|
442
449
|
|
443
450
|
it "should no preload comments => post" do
|
444
|
-
Comment.
|
451
|
+
Comment.includes(:post).each do |comment|
|
445
452
|
comment.post.name
|
446
453
|
end
|
447
454
|
Bullet::Association.should_not be_has_unpreload_associations
|
448
455
|
end
|
449
456
|
|
450
457
|
it "should detect no unused preload comments => post" do
|
451
|
-
Comment.
|
458
|
+
Comment.all.collect(&:name)
|
452
459
|
Bullet::Association.check_unused_preload_associations
|
453
460
|
Bullet::Association.should_not be_has_unused_preload_associations
|
454
461
|
end
|
455
462
|
|
456
463
|
it "should detect unused preload comments => post" do
|
457
|
-
Comment.
|
464
|
+
Comment.includes(:post).collect(&:name)
|
458
465
|
Bullet::Association.check_unused_preload_associations
|
459
466
|
Bullet::Association.should be_has_unused_preload_associations
|
460
467
|
end
|
461
468
|
|
462
469
|
it "should dectect no unused preload comments => post" do
|
463
|
-
Comment.
|
470
|
+
Comment.all.each do |comment|
|
464
471
|
comment.post.name
|
465
472
|
end
|
466
473
|
Bullet::Association.check_unused_preload_associations
|
@@ -468,13 +475,13 @@ describe Bullet::Association, 'has_many' do
|
|
468
475
|
end
|
469
476
|
|
470
477
|
it "should dectect no unused preload comments => post" do
|
471
|
-
Comment.
|
478
|
+
Comment.includes(:post).each do |comment|
|
472
479
|
comment.post.name
|
473
480
|
end
|
474
481
|
Bullet::Association.check_unused_preload_associations
|
475
482
|
Bullet::Association.should_not be_has_unused_preload_associations
|
476
483
|
end
|
477
|
-
end
|
484
|
+
# end
|
478
485
|
end
|
479
486
|
|
480
487
|
describe Bullet::Association, 'has_and_belongs_to_many' do
|
@@ -535,27 +542,27 @@ describe Bullet::Association, 'has_and_belongs_to_many' do
|
|
535
542
|
end
|
536
543
|
|
537
544
|
it "should detect unpreload associations" do
|
538
|
-
Student.
|
545
|
+
Student.all.each do |student|
|
539
546
|
student.teachers.collect(&:name)
|
540
547
|
end
|
541
548
|
Bullet::Association.should be_has_unpreload_associations
|
542
549
|
end
|
543
550
|
|
544
551
|
it "should detect no unpreload associations" do
|
545
|
-
Student.
|
552
|
+
Student.includes(:teachers).each do |student|
|
546
553
|
student.teachers.collect(&:name)
|
547
554
|
end
|
548
555
|
Bullet::Association.should_not be_has_unpreload_associations
|
549
556
|
end
|
550
557
|
|
551
558
|
it "should detect unused preload associations" do
|
552
|
-
Student.
|
559
|
+
Student.includes(:teachers).collect(&:name)
|
553
560
|
Bullet::Association.check_unused_preload_associations
|
554
561
|
Bullet::Association.should be_has_unused_preload_associations
|
555
562
|
end
|
556
563
|
|
557
564
|
it "should detect no unused preload associations" do
|
558
|
-
Student.
|
565
|
+
Student.all.collect(&:name)
|
559
566
|
Bullet::Association.check_unused_preload_associations
|
560
567
|
Bullet::Association.should_not be_has_unused_preload_associations
|
561
568
|
end
|
@@ -573,7 +580,7 @@ describe Bullet::Association, 'has_many :through' do
|
|
573
580
|
t.column :name, :string
|
574
581
|
end
|
575
582
|
|
576
|
-
create_table :
|
583
|
+
create_table :relationships do |t|
|
577
584
|
t.column :firm_id, :integer
|
578
585
|
t.column :client_id, :integer
|
579
586
|
end
|
@@ -587,16 +594,16 @@ describe Bullet::Association, 'has_many :through' do
|
|
587
594
|
end
|
588
595
|
|
589
596
|
class Firm < ActiveRecord::Base
|
590
|
-
has_many :
|
591
|
-
has_many :clients, :through => :
|
597
|
+
has_many :relationships
|
598
|
+
has_many :clients, :through => :relationships
|
592
599
|
end
|
593
600
|
|
594
601
|
class Client < ActiveRecord::Base
|
595
|
-
has_many :
|
596
|
-
has_many :firms, :through => :
|
602
|
+
has_many :relationships
|
603
|
+
has_many :firms, :through => :relationships
|
597
604
|
end
|
598
605
|
|
599
|
-
class
|
606
|
+
class Relationship < ActiveRecord::Base
|
600
607
|
belongs_to :firm
|
601
608
|
belongs_to :client
|
602
609
|
end
|
@@ -626,27 +633,27 @@ describe Bullet::Association, 'has_many :through' do
|
|
626
633
|
end
|
627
634
|
|
628
635
|
it "should detect unpreload associations" do
|
629
|
-
Firm.
|
636
|
+
Firm.all.each do |firm|
|
630
637
|
firm.clients.collect(&:name)
|
631
638
|
end
|
632
639
|
Bullet::Association.should be_has_unpreload_associations
|
633
640
|
end
|
634
641
|
|
635
642
|
it "should detect no unpreload associations" do
|
636
|
-
Firm.
|
643
|
+
Firm.includes(:clients).each do |firm|
|
637
644
|
firm.clients.collect(&:name)
|
638
645
|
end
|
639
646
|
Bullet::Association.should_not be_has_unpreload_associations
|
640
647
|
end
|
641
648
|
|
642
649
|
it "should detect no unused preload associations" do
|
643
|
-
Firm.
|
650
|
+
Firm.all.collect(&:name)
|
644
651
|
Bullet::Association.check_unused_preload_associations
|
645
652
|
Bullet::Association.should_not be_has_unused_preload_associations
|
646
653
|
end
|
647
654
|
|
648
655
|
it "should detect unused preload associations" do
|
649
|
-
Firm.
|
656
|
+
Firm.includes(:clients).collect(&:name)
|
650
657
|
Bullet::Association.check_unused_preload_associations
|
651
658
|
Bullet::Association.should be_has_unused_preload_associations
|
652
659
|
end
|
@@ -742,63 +749,64 @@ describe Bullet::Association, 'has_many :as' do
|
|
742
749
|
|
743
750
|
# this happens only when a polymorphic association is included along with another table which is being referenced in the query
|
744
751
|
it "should not have unused preloaded associations with conditions" do
|
745
|
-
all_users = User.
|
746
|
-
users_with_ten_votes = User.
|
747
|
-
users_without_ten_votes = User.
|
748
|
-
all_users.
|
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) }
|
749
757
|
Bullet::Association.check_unused_preload_associations
|
750
758
|
Bullet::Association.should_not be_unused_preload_associations_for(User, :pets)
|
751
759
|
Bullet::Association.should_not be_unused_preload_associations_for(User, :votes)
|
752
760
|
end
|
753
761
|
|
754
762
|
it "should detect unpreload associations" do
|
755
|
-
User.
|
763
|
+
User.all.each do |user|
|
756
764
|
user.votes.collect(&:vote)
|
757
765
|
end
|
758
766
|
Bullet::Association.should be_has_unpreload_associations
|
759
767
|
end
|
760
768
|
|
761
769
|
it "should detect no unpreload associations" do
|
762
|
-
User.
|
770
|
+
User.includes(:votes).each do |user|
|
763
771
|
user.votes.collect(&:vote)
|
764
772
|
end
|
765
773
|
Bullet::Association.should_not be_has_unpreload_associations
|
766
774
|
end
|
767
775
|
|
768
776
|
it "should detect unpreload associations with voteable" do
|
769
|
-
Vote.
|
777
|
+
Vote.all.each do |vote|
|
770
778
|
vote.voteable.name
|
771
779
|
end
|
772
780
|
Bullet::Association.should be_has_unpreload_associations
|
773
781
|
end
|
774
782
|
|
775
783
|
it "should detect no unpreload associations with voteable" do
|
776
|
-
Vote.
|
784
|
+
Vote.includes(:voteable).each do |vote|
|
777
785
|
vote.voteable.name
|
778
786
|
end
|
779
787
|
Bullet::Association.should_not be_has_unpreload_associations
|
780
788
|
end
|
781
789
|
|
782
790
|
it "should detect no unused preload associations" do
|
783
|
-
User.
|
791
|
+
User.all.collect(&:name)
|
784
792
|
Bullet::Association.check_unused_preload_associations
|
785
793
|
Bullet::Association.should_not be_has_unused_preload_associations
|
786
794
|
end
|
787
795
|
|
788
796
|
it "should detect unused preload associations" do
|
789
|
-
User.
|
797
|
+
User.includes(:votes).collect(&:name)
|
790
798
|
Bullet::Association.check_unused_preload_associations
|
791
799
|
Bullet::Association.should be_has_unused_preload_associations
|
792
800
|
end
|
793
801
|
|
794
802
|
it "should detect no unused preload associations with voteable" do
|
795
|
-
Vote.
|
803
|
+
Vote.all.collect(&:vote)
|
796
804
|
Bullet::Association.check_unused_preload_associations
|
797
805
|
Bullet::Association.should_not be_has_unused_preload_associations
|
798
806
|
end
|
799
807
|
|
800
808
|
it "should detect unused preload associations with voteable" do
|
801
|
-
Vote.
|
809
|
+
Vote.includes(:voteable).collect(&:vote)
|
802
810
|
Bullet::Association.check_unused_preload_associations
|
803
811
|
Bullet::Association.should be_has_unused_preload_associations
|
804
812
|
end
|
@@ -856,7 +864,7 @@ describe Bullet::Association, "has_one" do
|
|
856
864
|
end
|
857
865
|
|
858
866
|
it "should detect unpreload association" do
|
859
|
-
Company.
|
867
|
+
Company.all.each do |company|
|
860
868
|
company.address.name
|
861
869
|
end
|
862
870
|
Bullet::Association.should be_has_unpreload_associations
|
@@ -870,7 +878,7 @@ describe Bullet::Association, "has_one" do
|
|
870
878
|
end
|
871
879
|
|
872
880
|
it "should detect no unused preload association" do
|
873
|
-
Company.
|
881
|
+
Company.all.collect(&:name)
|
874
882
|
Bullet::Association.check_unused_preload_associations
|
875
883
|
Bullet::Association.should_not be_has_unused_preload_associations
|
876
884
|
end
|
@@ -936,7 +944,7 @@ describe Bullet::Association, "call one association that in possible objects" do
|
|
936
944
|
end
|
937
945
|
|
938
946
|
it "should detect no unpreload association" do
|
939
|
-
Contact.
|
947
|
+
Contact.all
|
940
948
|
Contact.first.emails.collect(&:name)
|
941
949
|
Bullet::Association.should_not be_has_unpreload_associations
|
942
950
|
end
|
@@ -1002,7 +1010,7 @@ describe Bullet::Association, "STI" do
|
|
1002
1010
|
end
|
1003
1011
|
|
1004
1012
|
it "should detect unpreload associations" do
|
1005
|
-
Page.
|
1013
|
+
Page.all.each do |page|
|
1006
1014
|
page.author.name
|
1007
1015
|
end
|
1008
1016
|
Bullet::Association.should be_has_unpreload_associations
|
@@ -1027,7 +1035,7 @@ describe Bullet::Association, "STI" do
|
|
1027
1035
|
end
|
1028
1036
|
|
1029
1037
|
it "should not detect unused preload associations" do
|
1030
|
-
Page.
|
1038
|
+
Page.all.collect(&:name)
|
1031
1039
|
Bullet::Association.should_not be_has_unpreload_associations
|
1032
1040
|
Bullet::Association.check_unused_preload_associations
|
1033
1041
|
Bullet::Association.should_not be_has_unused_preload_associations
|