bullet 5.6.0 → 5.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.rails-5.2 +15 -0
- data/Guardfile +2 -2
- data/Rakefile +16 -17
- data/bullet.gemspec +11 -11
- data/lib/bullet/active_record52.rb +225 -0
- data/lib/bullet/dependency.rb +6 -0
- data/lib/bullet/detector/association.rb +3 -2
- data/lib/bullet/detector/counter_cache.rb +4 -3
- data/lib/bullet/detector/n_plus_one_query.rb +6 -5
- data/lib/bullet/detector/unused_eager_loading.rb +4 -3
- data/lib/bullet/ext/string.rb +1 -1
- data/lib/bullet/mongoid4x.rb +1 -1
- data/lib/bullet/mongoid5x.rb +1 -1
- data/lib/bullet/mongoid6x.rb +1 -1
- data/lib/bullet/notification/base.rb +9 -8
- data/lib/bullet/notification/counter_cache.rb +1 -1
- data/lib/bullet/notification/n_plus_one_query.rb +2 -1
- data/lib/bullet/notification/unused_eager_loading.rb +2 -1
- data/lib/bullet/rack.rb +5 -5
- data/lib/bullet/stack_trace_filter.rb +2 -2
- data/lib/bullet/version.rb +2 -2
- data/lib/bullet.rb +15 -7
- data/lib/generators/bullet/install_generator.rb +5 -5
- data/perf/benchmark.rb +6 -8
- data/spec/bullet/detector/association_spec.rb +4 -4
- data/spec/bullet/detector/counter_cache_spec.rb +11 -11
- data/spec/bullet/detector/n_plus_one_query_spec.rb +35 -35
- data/spec/bullet/detector/unused_eager_loading_spec.rb +19 -19
- data/spec/bullet/ext/object_spec.rb +7 -7
- data/spec/bullet/ext/string_spec.rb +5 -5
- data/spec/bullet/notification/base_spec.rb +32 -33
- data/spec/bullet/notification/counter_cache_spec.rb +2 -2
- data/spec/bullet/notification/n_plus_one_query_spec.rb +3 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +2 -2
- data/spec/bullet/notification_collector_spec.rb +10 -10
- data/spec/bullet/rack_spec.rb +46 -46
- data/spec/bullet/registry/association_spec.rb +10 -10
- data/spec/bullet/registry/base_spec.rb +20 -20
- data/spec/bullet/registry/object_spec.rb +4 -4
- data/spec/bullet_spec.rb +20 -1
- data/spec/integration/active_record/association_spec.rb +106 -106
- data/spec/integration/counter_cache_spec.rb +12 -12
- data/spec/integration/mongoid/association_spec.rb +33 -33
- data/spec/models/comment.rb +1 -1
- data/spec/models/document.rb +2 -2
- data/spec/models/mongoid/address.rb +1 -1
- data/spec/models/mongoid/category.rb +2 -2
- data/spec/models/mongoid/comment.rb +1 -1
- data/spec/models/mongoid/company.rb +1 -1
- data/spec/models/mongoid/entry.rb +1 -1
- data/spec/models/mongoid/post.rb +3 -3
- data/spec/models/newspaper.rb +1 -1
- data/spec/spec_helper.rb +12 -12
- data/spec/support/mongo_seed.rb +6 -6
- data/spec/support/rack_double.rb +4 -3
- data/spec/support/sqlite_seed.rb +6 -7
- data/tasks/bullet_tasks.rake +2 -2
- data/test.sh +2 -0
- data/update.sh +2 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7c9650d2dbc870d2ac04be4ca0e19723ef6a85c2
|
|
4
|
+
data.tar.gz: 35839d605fb1e11687836dbcbe12572b1eb07775
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5064948ab9db44cc9b4082397990a3d91e93dc6986db2767a528a4a05734b1d1ba9231af337624d79d7e312d13e075afb53217191d017a3c511a0889c436d0a0
|
|
7
|
+
data.tar.gz: 2c12bd045e5e41b4db0761b07562a763d3be089231d5e420fc3d7d8d27a40f184216c9090667883a606e35fcdfd2eda3f276838e60696c642bff0939ab35e85f
|
data/CHANGELOG.md
CHANGED
data/Gemfile.rails-5.2
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gemspec
|
|
4
|
+
|
|
5
|
+
gem 'rails', '~> 5.2.0.beta1'
|
|
6
|
+
gem 'sqlite3'
|
|
7
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: [:jruby]
|
|
8
|
+
gem 'activerecord-import'
|
|
9
|
+
|
|
10
|
+
gem "rspec"
|
|
11
|
+
|
|
12
|
+
platforms :rbx do
|
|
13
|
+
gem 'rubysl', '~> 2.0'
|
|
14
|
+
gem 'rubinius-developer_tools'
|
|
15
|
+
end
|
data/Guardfile
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# A sample Guardfile
|
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
|
3
3
|
|
|
4
|
-
guard 'rspec', :version => 2, :all_after_pass => false, :all_on_start => false, :cli =>
|
|
4
|
+
guard 'rspec', :version => 2, :all_after_pass => false, :all_on_start => false, :cli => '--color --format nested --fail-fast' do
|
|
5
5
|
watch(%r{^spec/.+_spec\.rb$})
|
|
6
6
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
7
|
-
watch('spec/spec_helper.rb') {
|
|
7
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
|
8
8
|
end
|
data/Rakefile
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
$LOAD_PATH.unshift File.expand_path(
|
|
2
|
-
require
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
|
2
|
+
require 'bundler'
|
|
3
3
|
Bundler.setup
|
|
4
4
|
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
5
|
+
require 'rake'
|
|
6
|
+
require 'rspec'
|
|
7
|
+
require 'rspec/core/rake_task'
|
|
8
8
|
|
|
9
|
-
require
|
|
9
|
+
require 'bullet/version'
|
|
10
10
|
|
|
11
11
|
task :build do
|
|
12
|
-
system
|
|
12
|
+
system 'gem build bullet.gemspec'
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
task :install => :build do
|
|
@@ -19,31 +19,30 @@ end
|
|
|
19
19
|
task :release => :build do
|
|
20
20
|
puts "Tagging #{Bullet::VERSION}..."
|
|
21
21
|
system "git tag -a #{Bullet::VERSION} -m 'Tagging #{Bullet::VERSION}'"
|
|
22
|
-
puts
|
|
23
|
-
system
|
|
24
|
-
puts
|
|
22
|
+
puts 'Pushing to Github...'
|
|
23
|
+
system 'git push --tags'
|
|
24
|
+
puts 'Pushing to rubygems.org...'
|
|
25
25
|
system "gem push bullet-#{Bullet::VERSION}.gem"
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
|
29
|
-
spec.pattern =
|
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
RSpec::Core::RakeTask.new('spec:progress') do |spec|
|
|
33
33
|
spec.rspec_opts = %w(--format progress)
|
|
34
|
-
spec.pattern =
|
|
34
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
|
|
38
37
|
begin
|
|
39
38
|
require 'rdoc/task'
|
|
40
39
|
|
|
41
|
-
desc
|
|
40
|
+
desc 'Generate documentation for the plugin.'
|
|
42
41
|
Rake::RDocTask.new do |rdoc|
|
|
43
|
-
rdoc.rdoc_dir =
|
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
44
43
|
rdoc.title = "bullet #{Bullet::VERSION}"
|
|
45
|
-
rdoc.rdoc_files.include(
|
|
46
|
-
rdoc.rdoc_files.include(
|
|
44
|
+
rdoc.rdoc_files.include('README*')
|
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
47
46
|
end
|
|
48
47
|
rescue LoadError
|
|
49
48
|
puts 'RDocTask is not supported for this platform'
|
data/bullet.gemspec
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
lib = File.expand_path('../lib/', __FILE__)
|
|
2
2
|
$:.unshift lib unless $:.include?(lib)
|
|
3
3
|
|
|
4
|
-
require
|
|
4
|
+
require 'bullet/version'
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
|
-
s.name =
|
|
7
|
+
s.name = 'bullet'
|
|
8
8
|
s.version = Bullet::VERSION
|
|
9
9
|
s.platform = Gem::Platform::RUBY
|
|
10
|
-
s.authors = [
|
|
11
|
-
s.email = [
|
|
12
|
-
s.homepage =
|
|
13
|
-
s.summary =
|
|
14
|
-
s.description =
|
|
10
|
+
s.authors = ['Richard Huang']
|
|
11
|
+
s.email = ['flyerhzm@gmail.com']
|
|
12
|
+
s.homepage = 'http://github.com/flyerhzm/bullet'
|
|
13
|
+
s.summary = 'help to kill N+1 queries and unused eager loading.'
|
|
14
|
+
s.description = 'help to kill N+1 queries and unused eager loading.'
|
|
15
15
|
|
|
16
16
|
s.license = 'MIT'
|
|
17
17
|
|
|
18
|
-
s.required_rubygems_version =
|
|
18
|
+
s.required_rubygems_version = '>= 1.3.6'
|
|
19
19
|
|
|
20
|
-
s.add_runtime_dependency
|
|
21
|
-
s.add_runtime_dependency
|
|
20
|
+
s.add_runtime_dependency 'activesupport', '>= 3.0.0'
|
|
21
|
+
s.add_runtime_dependency 'uniform_notifier', '~> 1.10.0'
|
|
22
22
|
|
|
23
23
|
s.files = `git ls-files`.split("\n")
|
|
24
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
25
|
-
s.require_paths = [
|
|
25
|
+
s.require_paths = ['lib']
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
module Bullet
|
|
2
|
+
module SaveWithBulletSupport
|
|
3
|
+
def save(*args)
|
|
4
|
+
was_new_record = new_record?
|
|
5
|
+
super(*args).tap do |result|
|
|
6
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def save!(*args)
|
|
11
|
+
was_new_record = new_record?
|
|
12
|
+
super(*args).tap do |result|
|
|
13
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self) if result && was_new_record
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module ActiveRecord
|
|
19
|
+
def self.enable
|
|
20
|
+
require 'active_record'
|
|
21
|
+
::ActiveRecord::Base.extend(Module.new {
|
|
22
|
+
def find_by_sql(sql, binds = [], preparable: nil, &block)
|
|
23
|
+
result = super
|
|
24
|
+
if Bullet.start?
|
|
25
|
+
if result.is_a? Array
|
|
26
|
+
if result.size > 1
|
|
27
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
28
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
|
29
|
+
elsif result.size == 1
|
|
30
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
|
31
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
|
32
|
+
end
|
|
33
|
+
elsif result.is_a? ::ActiveRecord::Base
|
|
34
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
|
|
35
|
+
Bullet::Detector::CounterCache.add_impossible_object(result)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
result
|
|
39
|
+
end
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
::ActiveRecord::Base.prepend(SaveWithBulletSupport)
|
|
43
|
+
|
|
44
|
+
::ActiveRecord::Relation.prepend(Module.new {
|
|
45
|
+
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
|
46
|
+
# if select only one object, then the only one object has impossible to cause N+1 query.
|
|
47
|
+
def records
|
|
48
|
+
result = super
|
|
49
|
+
if Bullet.start?
|
|
50
|
+
if result.first.class.name !~ /^HABTM_/
|
|
51
|
+
if result.size > 1
|
|
52
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
|
53
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
|
54
|
+
elsif result.size == 1
|
|
55
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
|
56
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
result
|
|
61
|
+
end
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
::ActiveRecord::Associations::Preloader.prepend(Module.new {
|
|
65
|
+
def preloaders_for_one(association, records, scope)
|
|
66
|
+
if Bullet.start?
|
|
67
|
+
records.compact!
|
|
68
|
+
if records.first.class.name !~ /^HABTM_/
|
|
69
|
+
records.each do |record|
|
|
70
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
|
71
|
+
end
|
|
72
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, association)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
super
|
|
76
|
+
end
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
::ActiveRecord::FinderMethods.prepend(Module.new {
|
|
80
|
+
# add includes in scope
|
|
81
|
+
def find_with_associations
|
|
82
|
+
return super { |r| yield r } if block_given?
|
|
83
|
+
records = super
|
|
84
|
+
if Bullet.start?
|
|
85
|
+
associations = (eager_load_values + includes_values).uniq
|
|
86
|
+
records.each do |record|
|
|
87
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
88
|
+
end
|
|
89
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(records, associations)
|
|
90
|
+
end
|
|
91
|
+
records
|
|
92
|
+
end
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
::ActiveRecord::Associations::JoinDependency.prepend(Module.new {
|
|
96
|
+
def instantiate(result_set, &block)
|
|
97
|
+
@bullet_eager_loadings = {}
|
|
98
|
+
records = super
|
|
99
|
+
|
|
100
|
+
if Bullet.start?
|
|
101
|
+
@bullet_eager_loadings.each do |klazz, eager_loadings_hash|
|
|
102
|
+
objects = eager_loadings_hash.keys
|
|
103
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(objects, eager_loadings_hash[objects.first].to_a)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
records
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
|
|
110
|
+
if Bullet.start?
|
|
111
|
+
unless ar_parent.nil?
|
|
112
|
+
parent.children.each do |node|
|
|
113
|
+
key = aliases.column_alias(node, node.primary_key)
|
|
114
|
+
id = row[key]
|
|
115
|
+
if id.nil?
|
|
116
|
+
associations = node.reflection.name
|
|
117
|
+
Bullet::Detector::Association.add_object_associations(ar_parent, associations)
|
|
118
|
+
Bullet::Detector::NPlusOneQuery.call_association(ar_parent, associations)
|
|
119
|
+
@bullet_eager_loadings[ar_parent.class] ||= {}
|
|
120
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
|
|
121
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] << associations
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
super
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# call join associations
|
|
131
|
+
def construct_model(record, node, row, model_cache, id, aliases)
|
|
132
|
+
result = super
|
|
133
|
+
|
|
134
|
+
if Bullet.start?
|
|
135
|
+
associations = node.reflection.name
|
|
136
|
+
Bullet::Detector::Association.add_object_associations(record, associations)
|
|
137
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, associations)
|
|
138
|
+
@bullet_eager_loadings[record.class] ||= {}
|
|
139
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
|
140
|
+
@bullet_eager_loadings[record.class][record] << associations
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
result
|
|
144
|
+
end
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
::ActiveRecord::Associations::CollectionAssociation.prepend(Module.new {
|
|
148
|
+
def load_target
|
|
149
|
+
records = super
|
|
150
|
+
|
|
151
|
+
if Bullet.start?
|
|
152
|
+
if self.is_a? ::ActiveRecord::Associations::ThroughAssociation
|
|
153
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
|
|
154
|
+
association = self.owner.association self.through_reflection.name
|
|
155
|
+
Array(association.target).each do |through_record|
|
|
156
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) unless @inversed
|
|
160
|
+
if records.first.class.name !~ /^HABTM_/
|
|
161
|
+
if records.size > 1
|
|
162
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
163
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
|
164
|
+
elsif records.size == 1
|
|
165
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
|
166
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
records
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def empty?
|
|
174
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
|
175
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
|
176
|
+
end
|
|
177
|
+
super
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def include?(object)
|
|
181
|
+
if Bullet.start?
|
|
182
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
|
183
|
+
end
|
|
184
|
+
super
|
|
185
|
+
end
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
::ActiveRecord::Associations::SingularAssociation.prepend(Module.new {
|
|
189
|
+
# call has_one and belongs_to associations
|
|
190
|
+
def target
|
|
191
|
+
result = super()
|
|
192
|
+
if Bullet.start?
|
|
193
|
+
if owner.class.name !~ /^HABTM_/ && !@inversed
|
|
194
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
|
195
|
+
if Bullet::Detector::NPlusOneQuery.impossible?(owner)
|
|
196
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
|
197
|
+
else
|
|
198
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
result
|
|
203
|
+
end
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
::ActiveRecord::Associations::HasManyAssociation.prepend(Module.new {
|
|
207
|
+
def empty?
|
|
208
|
+
result = super
|
|
209
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
|
210
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
|
211
|
+
end
|
|
212
|
+
result
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def count_records
|
|
216
|
+
result = reflection.has_cached_counter?
|
|
217
|
+
if Bullet.start? && !result && !self.is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
|
218
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
|
219
|
+
end
|
|
220
|
+
super
|
|
221
|
+
end
|
|
222
|
+
})
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
data/lib/bullet/dependency.rb
CHANGED
|
@@ -24,6 +24,8 @@ module Bullet
|
|
|
24
24
|
'active_record5'
|
|
25
25
|
elsif active_record51?
|
|
26
26
|
'active_record5'
|
|
27
|
+
elsif active_record52?
|
|
28
|
+
'active_record52'
|
|
27
29
|
else
|
|
28
30
|
raise "Bullet does not support active_record #{::ActiveRecord::VERSION} yet"
|
|
29
31
|
end
|
|
@@ -72,6 +74,10 @@ module Bullet
|
|
|
72
74
|
active_record5? && ::ActiveRecord::VERSION::MINOR == 1
|
|
73
75
|
end
|
|
74
76
|
|
|
77
|
+
def active_record52?
|
|
78
|
+
active_record5? && ::ActiveRecord::VERSION::MINOR == 2
|
|
79
|
+
end
|
|
80
|
+
|
|
75
81
|
def mongoid4x?
|
|
76
82
|
mongoid? && ::Mongoid::VERSION =~ /\A4/
|
|
77
83
|
end
|
|
@@ -7,7 +7,7 @@ module Bullet
|
|
|
7
7
|
return if !Bullet.n_plus_one_query_enable? && !Bullet.unused_eager_loading_enable?
|
|
8
8
|
return unless object.primary_key_value
|
|
9
9
|
|
|
10
|
-
Bullet.debug(
|
|
10
|
+
Bullet.debug('Detector::Association#add_object_associations'.freeze, "object: #{object.bullet_key}, associations: #{associations}")
|
|
11
11
|
object_associations.add(object.bullet_key, associations)
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -16,7 +16,7 @@ module Bullet
|
|
|
16
16
|
return if !Bullet.n_plus_one_query_enable? && !Bullet.unused_eager_loading_enable?
|
|
17
17
|
return unless object.primary_key_value
|
|
18
18
|
|
|
19
|
-
Bullet.debug(
|
|
19
|
+
Bullet.debug('Detector::Association#add_call_object_associations'.freeze, "object: #{object.bullet_key}, associations: #{associations}")
|
|
20
20
|
call_object_associations.add(object.bullet_key, associations)
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -37,6 +37,7 @@ module Bullet
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
private
|
|
40
|
+
|
|
40
41
|
# object_associations keep the object relationships
|
|
41
42
|
# that the object has many associations.
|
|
42
43
|
# e.g. { "Post:1" => [:comments] }
|
|
@@ -7,7 +7,7 @@ module Bullet
|
|
|
7
7
|
return unless Bullet.counter_cache_enable?
|
|
8
8
|
return unless object.primary_key_value
|
|
9
9
|
|
|
10
|
-
Bullet.debug(
|
|
10
|
+
Bullet.debug('Detector::CounterCache#add_counter_cache', "object: #{object.bullet_key}, associations: #{associations}")
|
|
11
11
|
if conditions_met?(object, associations)
|
|
12
12
|
create_notification object.class.to_s, associations
|
|
13
13
|
end
|
|
@@ -19,7 +19,7 @@ module Bullet
|
|
|
19
19
|
objects = Array(object_or_objects)
|
|
20
20
|
return if objects.map(&:primary_key_value).compact.empty?
|
|
21
21
|
|
|
22
|
-
Bullet.debug(
|
|
22
|
+
Bullet.debug('Detector::CounterCache#add_possible_objects', "objects: #{objects.map(&:bullet_key).join(', ')}")
|
|
23
23
|
objects.each { |object| possible_objects.add object.bullet_key }
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -28,7 +28,7 @@ module Bullet
|
|
|
28
28
|
return unless Bullet.counter_cache_enable?
|
|
29
29
|
return unless object.primary_key_value
|
|
30
30
|
|
|
31
|
-
Bullet.debug(
|
|
31
|
+
Bullet.debug('Detector::CounterCache#add_impossible_object', "object: #{object.bullet_key}")
|
|
32
32
|
impossible_objects.add object.bullet_key
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -45,6 +45,7 @@ module Bullet
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
private
|
|
48
|
+
|
|
48
49
|
def create_notification(klazz, associations)
|
|
49
50
|
notify_associations = Array(associations) - Bullet.get_whitelist_associations(:counter_cache, klazz)
|
|
50
51
|
|
|
@@ -16,9 +16,9 @@ module Bullet
|
|
|
16
16
|
return if inversed_objects.include?(object.bullet_key, associations)
|
|
17
17
|
add_call_object_associations(object, associations)
|
|
18
18
|
|
|
19
|
-
Bullet.debug(
|
|
19
|
+
Bullet.debug('Detector::NPlusOneQuery#call_association'.freeze, "object: #{object.bullet_key}, associations: #{associations}")
|
|
20
20
|
if !excluded_stacktrace_path? && conditions_met?(object, associations)
|
|
21
|
-
Bullet.debug(
|
|
21
|
+
Bullet.debug('detect n + 1 query', "object: #{object.bullet_key}, associations: #{associations}")
|
|
22
22
|
create_notification caller_in_project, object.class.to_s, associations
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -29,7 +29,7 @@ module Bullet
|
|
|
29
29
|
objects = Array(object_or_objects)
|
|
30
30
|
return if objects.map(&:primary_key_value).compact.empty?
|
|
31
31
|
|
|
32
|
-
Bullet.debug(
|
|
32
|
+
Bullet.debug('Detector::NPlusOneQuery#add_possible_objects'.freeze, "objects: #{objects.map(&:bullet_key).join(', '.freeze)}")
|
|
33
33
|
objects.each { |object| possible_objects.add object.bullet_key }
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -38,7 +38,7 @@ module Bullet
|
|
|
38
38
|
return unless Bullet.n_plus_one_query_enable?
|
|
39
39
|
return unless object.primary_key_value
|
|
40
40
|
|
|
41
|
-
Bullet.debug(
|
|
41
|
+
Bullet.debug('Detector::NPlusOneQuery#add_impossible_object'.freeze, "object: #{object.bullet_key}")
|
|
42
42
|
impossible_objects.add object.bullet_key
|
|
43
43
|
end
|
|
44
44
|
|
|
@@ -47,7 +47,7 @@ module Bullet
|
|
|
47
47
|
return unless Bullet.n_plus_one_query_enable?
|
|
48
48
|
return unless object.primary_key_value
|
|
49
49
|
|
|
50
|
-
Bullet.debug(
|
|
50
|
+
Bullet.debug('Detector::NPlusOneQuery#add_inversed_object'.freeze, "object: #{object.bullet_key}, association: #{association}")
|
|
51
51
|
inversed_objects.add object.bullet_key, association
|
|
52
52
|
end
|
|
53
53
|
|
|
@@ -81,6 +81,7 @@ module Bullet
|
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
private
|
|
84
|
+
|
|
84
85
|
def create_notification(callers, klazz, associations)
|
|
85
86
|
notify_associations = Array(associations) - Bullet.get_whitelist_associations(:n_plus_one_query, klazz)
|
|
86
87
|
|
|
@@ -17,7 +17,7 @@ module Bullet
|
|
|
17
17
|
object_association_diff = diff_object_associations bullet_key, associations
|
|
18
18
|
next if object_association_diff.empty?
|
|
19
19
|
|
|
20
|
-
Bullet.debug(
|
|
20
|
+
Bullet.debug('detect unused preload', "object: #{bullet_key}, associations: #{object_association_diff}")
|
|
21
21
|
create_notification(caller_in_project, bullet_key.bullet_class_name, object_association_diff)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -27,7 +27,7 @@ module Bullet
|
|
|
27
27
|
return unless Bullet.unused_eager_loading_enable?
|
|
28
28
|
return if objects.map(&:primary_key_value).compact.empty?
|
|
29
29
|
|
|
30
|
-
Bullet.debug(
|
|
30
|
+
Bullet.debug('Detector::UnusedEagerLoading#add_eager_loadings', "objects: #{objects.map(&:bullet_key).join(', ')}, associations: #{associations}")
|
|
31
31
|
bullet_keys = objects.map(&:bullet_key)
|
|
32
32
|
|
|
33
33
|
to_add, to_merge, to_delete = [], [], []
|
|
@@ -40,7 +40,7 @@ module Bullet
|
|
|
40
40
|
if key_objects_overlap == k
|
|
41
41
|
to_add << [k, associations]
|
|
42
42
|
else
|
|
43
|
-
to_merge << [key_objects_overlap, (
|
|
43
|
+
to_merge << [key_objects_overlap, (eager_loadings[k].dup << associations)]
|
|
44
44
|
|
|
45
45
|
keys_without_objects = k - key_objects_overlap
|
|
46
46
|
to_merge << [keys_without_objects, eager_loadings[k]]
|
|
@@ -56,6 +56,7 @@ module Bullet
|
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
private
|
|
59
|
+
|
|
59
60
|
def create_notification(callers, klazz, associations)
|
|
60
61
|
notify_associations = Array(associations) - Bullet.get_whitelist_associations(:unused_eager_loading, klazz)
|
|
61
62
|
|
data/lib/bullet/ext/string.rb
CHANGED
data/lib/bullet/mongoid4x.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Bullet
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def each(&block)
|
|
24
|
-
records = query.map{ |doc| ::Mongoid::Factory.from_db(klass, doc) }
|
|
24
|
+
records = query.map { |doc| ::Mongoid::Factory.from_db(klass, doc) }
|
|
25
25
|
if records.length > 1
|
|
26
26
|
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
27
27
|
elsif records.size == 1
|
data/lib/bullet/mongoid5x.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Bullet
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def each(&block)
|
|
24
|
-
records = view.map{ |doc| ::Mongoid::Factory.from_db(klass, doc) }
|
|
24
|
+
records = view.map { |doc| ::Mongoid::Factory.from_db(klass, doc) }
|
|
25
25
|
if records.length > 1
|
|
26
26
|
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
27
27
|
elsif records.size == 1
|
data/lib/bullet/mongoid6x.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Bullet
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def each(&block)
|
|
24
|
-
records = view.map{ |doc| ::Mongoid::Factory.from_db(klass, doc) }
|
|
24
|
+
records = view.map { |doc| ::Mongoid::Factory.from_db(klass, doc) }
|
|
25
25
|
if records.length > 1
|
|
26
26
|
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
|
27
27
|
elsif records.size == 1
|
|
@@ -6,28 +6,28 @@ module Bullet
|
|
|
6
6
|
|
|
7
7
|
def initialize(base_class, association_or_associations, path = nil)
|
|
8
8
|
@base_class = base_class
|
|
9
|
-
@associations = association_or_associations.is_a?(Array) ?
|
|
9
|
+
@associations = association_or_associations.is_a?(Array) ? association_or_associations : [association_or_associations]
|
|
10
10
|
@path = path
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def title
|
|
14
|
-
raise NoMethodError.new(
|
|
14
|
+
raise NoMethodError.new('no method title defined')
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def body
|
|
18
|
-
raise NoMethodError.new(
|
|
18
|
+
raise NoMethodError.new('no method body defined')
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def call_stack_messages
|
|
22
|
-
|
|
22
|
+
''
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def whoami
|
|
26
|
-
@user ||= ENV['USER'].presence || (`whoami`.chomp rescue
|
|
26
|
+
@user ||= ENV['USER'].presence || (`whoami`.chomp rescue '')
|
|
27
27
|
if @user.present?
|
|
28
28
|
"user: #{@user}"
|
|
29
29
|
else
|
|
30
|
-
|
|
30
|
+
''
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -44,7 +44,7 @@ module Bullet
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def short_notice
|
|
47
|
-
[whoami.presence, url, title, body].compact.join(
|
|
47
|
+
[whoami.presence, url, title, body].compact.join(' ')
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def notification_data
|
|
@@ -65,12 +65,13 @@ module Bullet
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
protected
|
|
68
|
+
|
|
68
69
|
def klazz_associations_str
|
|
69
70
|
" #{@base_class} => [#{@associations.map(&:inspect).join(', '.freeze)}]"
|
|
70
71
|
end
|
|
71
72
|
|
|
72
73
|
def associations_str
|
|
73
|
-
":includes => #{@associations.map{ |a| a.to_s.to_sym unless a.is_a? Hash }.inspect}"
|
|
74
|
+
":includes => #{@associations.map { |a| a.to_s.to_sym unless a.is_a? Hash }.inspect}"
|
|
74
75
|
end
|
|
75
76
|
end
|
|
76
77
|
end
|