bullet 7.0.7 → 7.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -2
  3. data/README.md +7 -3
  4. data/lib/bullet/active_record4.rb +21 -6
  5. data/lib/bullet/active_record41.rb +21 -6
  6. data/lib/bullet/active_record42.rb +32 -12
  7. data/lib/bullet/active_record5.rb +40 -12
  8. data/lib/bullet/active_record52.rb +40 -12
  9. data/lib/bullet/active_record60.rb +40 -12
  10. data/lib/bullet/active_record61.rb +40 -12
  11. data/lib/bullet/active_record70.rb +54 -20
  12. data/lib/bullet/active_record71.rb +318 -0
  13. data/lib/bullet/dependency.rb +12 -0
  14. data/lib/bullet/detector/n_plus_one_query.rb +2 -5
  15. data/lib/bullet/detector/unused_eager_loading.rb +5 -2
  16. data/lib/bullet/ext/object.rb +14 -3
  17. data/lib/bullet/mongoid8x.rb +59 -0
  18. data/lib/bullet/notification/base.rb +22 -10
  19. data/lib/bullet/notification/counter_cache.rb +1 -1
  20. data/lib/bullet/rack.rb +4 -2
  21. data/lib/bullet/registry/association.rb +2 -1
  22. data/lib/bullet/stack_trace_filter.rb +3 -2
  23. data/lib/bullet/version.rb +1 -1
  24. data/lib/bullet.rb +11 -2
  25. metadata +7 -155
  26. data/.github/workflows/main.yml +0 -82
  27. data/.gitignore +0 -15
  28. data/.rspec +0 -2
  29. data/Gemfile +0 -24
  30. data/Gemfile.mongoid +0 -12
  31. data/Gemfile.mongoid-4.0 +0 -15
  32. data/Gemfile.mongoid-5.0 +0 -15
  33. data/Gemfile.mongoid-6.0 +0 -15
  34. data/Gemfile.mongoid-7.0 +0 -15
  35. data/Gemfile.rails-4.0 +0 -16
  36. data/Gemfile.rails-4.1 +0 -16
  37. data/Gemfile.rails-4.2 +0 -16
  38. data/Gemfile.rails-5.0 +0 -15
  39. data/Gemfile.rails-5.1 +0 -15
  40. data/Gemfile.rails-5.2 +0 -15
  41. data/Gemfile.rails-6.0 +0 -15
  42. data/Gemfile.rails-6.1 +0 -15
  43. data/Gemfile.rails-7.0 +0 -10
  44. data/Guardfile +0 -8
  45. data/Hacking.md +0 -75
  46. data/Rakefile +0 -51
  47. data/bullet.gemspec +0 -33
  48. data/perf/benchmark.rb +0 -118
  49. data/rails/init.rb +0 -3
  50. data/spec/bullet/detector/association_spec.rb +0 -28
  51. data/spec/bullet/detector/base_spec.rb +0 -10
  52. data/spec/bullet/detector/counter_cache_spec.rb +0 -58
  53. data/spec/bullet/detector/n_plus_one_query_spec.rb +0 -150
  54. data/spec/bullet/detector/unused_eager_loading_spec.rb +0 -126
  55. data/spec/bullet/ext/object_spec.rb +0 -44
  56. data/spec/bullet/ext/string_spec.rb +0 -15
  57. data/spec/bullet/notification/base_spec.rb +0 -94
  58. data/spec/bullet/notification/counter_cache_spec.rb +0 -14
  59. data/spec/bullet/notification/n_plus_one_query_spec.rb +0 -29
  60. data/spec/bullet/notification/unused_eager_loading_spec.rb +0 -18
  61. data/spec/bullet/notification_collector_spec.rb +0 -34
  62. data/spec/bullet/rack_spec.rb +0 -296
  63. data/spec/bullet/registry/association_spec.rb +0 -28
  64. data/spec/bullet/registry/base_spec.rb +0 -46
  65. data/spec/bullet/registry/object_spec.rb +0 -26
  66. data/spec/bullet/stack_trace_filter_spec.rb +0 -26
  67. data/spec/bullet_spec.rb +0 -136
  68. data/spec/integration/active_record/association_spec.rb +0 -822
  69. data/spec/integration/counter_cache_spec.rb +0 -68
  70. data/spec/integration/mongoid/association_spec.rb +0 -246
  71. data/spec/models/address.rb +0 -5
  72. data/spec/models/attachment.rb +0 -5
  73. data/spec/models/author.rb +0 -5
  74. data/spec/models/base_user.rb +0 -7
  75. data/spec/models/category.rb +0 -12
  76. data/spec/models/city.rb +0 -5
  77. data/spec/models/client.rb +0 -8
  78. data/spec/models/comment.rb +0 -8
  79. data/spec/models/company.rb +0 -5
  80. data/spec/models/country.rb +0 -5
  81. data/spec/models/deal.rb +0 -5
  82. data/spec/models/document.rb +0 -7
  83. data/spec/models/entry.rb +0 -5
  84. data/spec/models/firm.rb +0 -7
  85. data/spec/models/folder.rb +0 -4
  86. data/spec/models/group.rb +0 -4
  87. data/spec/models/mongoid/address.rb +0 -9
  88. data/spec/models/mongoid/category.rb +0 -10
  89. data/spec/models/mongoid/comment.rb +0 -9
  90. data/spec/models/mongoid/company.rb +0 -9
  91. data/spec/models/mongoid/entry.rb +0 -9
  92. data/spec/models/mongoid/post.rb +0 -14
  93. data/spec/models/mongoid/user.rb +0 -7
  94. data/spec/models/newspaper.rb +0 -5
  95. data/spec/models/page.rb +0 -4
  96. data/spec/models/person.rb +0 -5
  97. data/spec/models/pet.rb +0 -5
  98. data/spec/models/post.rb +0 -34
  99. data/spec/models/relationship.rb +0 -6
  100. data/spec/models/reply.rb +0 -5
  101. data/spec/models/role.rb +0 -7
  102. data/spec/models/student.rb +0 -5
  103. data/spec/models/submission.rb +0 -7
  104. data/spec/models/teacher.rb +0 -5
  105. data/spec/models/user.rb +0 -8
  106. data/spec/models/writer.rb +0 -4
  107. data/spec/spec_helper.rb +0 -97
  108. data/spec/support/bullet_ext.rb +0 -56
  109. data/spec/support/mongo_seed.rb +0 -59
  110. data/spec/support/rack_double.rb +0 -49
  111. data/spec/support/sqlite_seed.rb +0 -284
  112. data/test.sh +0 -15
  113. data/update.sh +0 -10
@@ -65,7 +65,9 @@ module Bullet
65
65
  def call
66
66
  if Bullet.start?
67
67
  @preloaders.each do |preloader|
68
- preloader.records.each { |record| Bullet::Detector::Association.add_object_associations(record, preloader.associations) }
68
+ preloader.records.each { |record|
69
+ Bullet::Detector::Association.add_object_associations(record, preloader.associations)
70
+ }
69
71
  Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
70
72
  end
71
73
  end
@@ -80,7 +82,9 @@ module Bullet
80
82
  if Bullet.start?
81
83
  reflection_records.compact!
82
84
  if reflection_records.first.class.name !~ /^HABTM_/
83
- reflection_records.each { |record| Bullet::Detector::Association.add_object_associations(record, reflection.name) }
85
+ reflection_records.each { |record|
86
+ Bullet::Detector::Association.add_object_associations(record, reflection.name)
87
+ }
84
88
  Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
85
89
  end
86
90
  end
@@ -91,16 +95,18 @@ module Bullet
91
95
 
92
96
  ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
93
97
  Module.new do
94
- def preloaded_records
95
- if Bullet.start? && !defined?(@preloaded_records)
96
- source_preloaders.each do |source_preloader|
97
- reflection_name = source_preloader.send(:reflection).name
98
- source_preloader.send(:owners).each do |owner|
98
+ def source_preloaders
99
+ if Bullet.start? && !defined?(@source_preloaders)
100
+ preloaders = super
101
+ preloaders.each do |preloader|
102
+ reflection_name = preloader.send(:reflection).name
103
+ preloader.send(:owners).each do |owner|
99
104
  Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
100
105
  end
101
106
  end
107
+ else
108
+ super
102
109
  end
103
- super
104
110
  end
105
111
  end
106
112
  )
@@ -131,12 +137,17 @@ module Bullet
131
137
  id = row[key]
132
138
  next unless id.nil?
133
139
 
134
- associations = node.reflection.name
135
- Bullet::Detector::Association.add_object_associations(ar_parent, associations)
136
- Bullet::Detector::NPlusOneQuery.call_association(ar_parent, associations)
137
- @bullet_eager_loadings[ar_parent.class] ||= {}
138
- @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
139
- @bullet_eager_loadings[ar_parent.class][ar_parent] << associations
140
+ associations = [node.reflection.name]
141
+ if node.reflection.through_reflection?
142
+ associations << node.reflection.through_reflection.name
143
+ end
144
+ associations.each do |association|
145
+ Bullet::Detector::Association.add_object_associations(ar_parent, association)
146
+ Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
147
+ @bullet_eager_loadings[ar_parent.class] ||= {}
148
+ @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
149
+ @bullet_eager_loadings[ar_parent.class][ar_parent] << association
150
+ end
140
151
  end
141
152
  end
142
153
  end
@@ -149,12 +160,17 @@ module Bullet
149
160
  result = super
150
161
 
151
162
  if Bullet.start?
152
- associations = node.reflection.name
153
- Bullet::Detector::Association.add_object_associations(record, associations)
154
- Bullet::Detector::NPlusOneQuery.call_association(record, associations)
155
- @bullet_eager_loadings[record.class] ||= {}
156
- @bullet_eager_loadings[record.class][record] ||= Set.new
157
- @bullet_eager_loadings[record.class][record] << associations
163
+ associations = [node.reflection.name]
164
+ if node.reflection.through_reflection?
165
+ associations << node.reflection.through_reflection.name
166
+ end
167
+ associations.each do |association|
168
+ Bullet::Detector::Association.add_object_associations(record, association)
169
+ Bullet::Detector::NPlusOneQuery.call_association(record, association)
170
+ @bullet_eager_loadings[record.class] ||= {}
171
+ @bullet_eager_loadings[record.class][record] ||= Set.new
172
+ @bullet_eager_loadings[record.class][record] << association
173
+ end
158
174
  end
159
175
 
160
176
  result
@@ -279,6 +295,24 @@ module Bullet
279
295
  end
280
296
  end
281
297
  )
298
+
299
+ ::ActiveRecord::Associations::CollectionProxy.prepend(
300
+ Module.new do
301
+ def count(column_name = nil)
302
+ if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
303
+ Bullet::Detector::CounterCache.add_counter_cache(
304
+ proxy_association.owner,
305
+ proxy_association.reflection.name
306
+ )
307
+ Bullet::Detector::NPlusOneQuery.call_association(
308
+ proxy_association.owner,
309
+ proxy_association.reflection.name
310
+ )
311
+ end
312
+ super(column_name)
313
+ end
314
+ end
315
+ )
282
316
  end
283
317
  end
284
318
  end
@@ -0,0 +1,318 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module SaveWithBulletSupport
5
+ def _create_record(*)
6
+ super do
7
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
8
+ yield(self) if block_given?
9
+ end
10
+ end
11
+ end
12
+
13
+ module ActiveRecord
14
+ def self.enable
15
+ require 'active_record'
16
+ ::ActiveRecord::Base.extend(
17
+ Module.new do
18
+ def find_by_sql(sql, binds = [], preparable: nil, &block)
19
+ result = super
20
+ if Bullet.start?
21
+ if result.is_a? Array
22
+ if result.size > 1
23
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
24
+ Bullet::Detector::CounterCache.add_possible_objects(result)
25
+ elsif result.size == 1
26
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
27
+ Bullet::Detector::CounterCache.add_impossible_object(result.first)
28
+ end
29
+ elsif result.is_a? ::ActiveRecord::Base
30
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
31
+ Bullet::Detector::CounterCache.add_impossible_object(result)
32
+ end
33
+ end
34
+ result
35
+ end
36
+ end
37
+ )
38
+
39
+ ::ActiveRecord::Base.prepend(SaveWithBulletSupport)
40
+
41
+ ::ActiveRecord::Relation.prepend(
42
+ Module.new do
43
+ # if select a collection of objects, then these objects have possible to cause N+1 query.
44
+ # if select only one object, then the only one object has impossible to cause N+1 query.
45
+ def records
46
+ result = super
47
+ if Bullet.start?
48
+ if result.first.class.name !~ /^HABTM_/
49
+ if result.size > 1
50
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
51
+ Bullet::Detector::CounterCache.add_possible_objects(result)
52
+ elsif result.size == 1
53
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
54
+ Bullet::Detector::CounterCache.add_impossible_object(result.first)
55
+ end
56
+ end
57
+ end
58
+ result
59
+ end
60
+ end
61
+ )
62
+
63
+ ::ActiveRecord::Associations::Preloader::Batch.prepend(
64
+ Module.new do
65
+ def call
66
+ if Bullet.start?
67
+ @preloaders.each do |preloader|
68
+ preloader.records.each { |record|
69
+ Bullet::Detector::Association.add_object_associations(record, preloader.associations)
70
+ }
71
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
72
+ end
73
+ end
74
+ super
75
+ end
76
+ end
77
+ )
78
+
79
+ ::ActiveRecord::Associations::Preloader::Branch.prepend(
80
+ Module.new do
81
+ def preloaders_for_reflection(reflection, reflection_records)
82
+ if Bullet.start?
83
+ reflection_records.compact!
84
+ if reflection_records.first.class.name !~ /^HABTM_/
85
+ reflection_records.each { |record|
86
+ Bullet::Detector::Association.add_object_associations(record, reflection.name)
87
+ }
88
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
89
+ end
90
+ end
91
+ super
92
+ end
93
+ end
94
+ )
95
+
96
+ ::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
97
+ Module.new do
98
+ def source_preloaders
99
+ if Bullet.start? && !defined?(@source_preloaders)
100
+ preloaders = super
101
+ preloaders.each do |preloader|
102
+ reflection_name = preloader.send(:reflection).name
103
+ preloader.send(:owners).each do |owner|
104
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
105
+ end
106
+ end
107
+ else
108
+ super
109
+ end
110
+ end
111
+ end
112
+ )
113
+
114
+ ::ActiveRecord::Associations::JoinDependency.prepend(
115
+ Module.new do
116
+ def instantiate(result_set, strict_loading_value, &block)
117
+ @bullet_eager_loadings = {}
118
+ records = super
119
+
120
+ if Bullet.start?
121
+ @bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
122
+ objects = eager_loadings_hash.keys
123
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
124
+ objects,
125
+ eager_loadings_hash[objects.first].to_a
126
+ )
127
+ end
128
+ end
129
+ records
130
+ end
131
+
132
+ def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
133
+ if Bullet.start?
134
+ unless ar_parent.nil?
135
+ parent.children.each do |node|
136
+ key = aliases.column_alias(node, node.primary_key)
137
+ id = row[key]
138
+ next unless id.nil?
139
+
140
+ associations = [node.reflection.name]
141
+ if node.reflection.through_reflection?
142
+ associations << node.reflection.through_reflection.name
143
+ end
144
+ associations.each do |association|
145
+ Bullet::Detector::Association.add_object_associations(ar_parent, association)
146
+ Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
147
+ @bullet_eager_loadings[ar_parent.class] ||= {}
148
+ @bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
149
+ @bullet_eager_loadings[ar_parent.class][ar_parent] << association
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ super
156
+ end
157
+
158
+ # call join associations
159
+ def construct_model(record, node, row, model_cache, id, strict_loading_value)
160
+ result = super
161
+
162
+ if Bullet.start?
163
+ associations = [node.reflection.name]
164
+ if node.reflection.through_reflection?
165
+ associations << node.reflection.through_reflection.name
166
+ end
167
+ associations.each do |association|
168
+ Bullet::Detector::Association.add_object_associations(record, association)
169
+ Bullet::Detector::NPlusOneQuery.call_association(record, association)
170
+ @bullet_eager_loadings[record.class] ||= {}
171
+ @bullet_eager_loadings[record.class][record] ||= Set.new
172
+ @bullet_eager_loadings[record.class][record] << association
173
+ end
174
+ end
175
+
176
+ result
177
+ end
178
+ end
179
+ )
180
+
181
+ ::ActiveRecord::Associations::Association.prepend(
182
+ Module.new do
183
+ def inversed_from(record)
184
+ if Bullet.start?
185
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
186
+ end
187
+ super
188
+ end
189
+
190
+ def inversed_from_queries(record)
191
+ if Bullet.start? && inversable?(record)
192
+ Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
193
+ end
194
+ super
195
+ end
196
+ end
197
+ )
198
+
199
+ ::ActiveRecord::Associations::CollectionAssociation.prepend(
200
+ Module.new do
201
+ def load_target
202
+ records = super
203
+
204
+ if Bullet.start?
205
+ if is_a? ::ActiveRecord::Associations::ThroughAssociation
206
+ association = owner.association(reflection.through_reflection.name)
207
+ if association.loaded?
208
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
209
+ Array.wrap(association.target).each do |through_record|
210
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
211
+ end
212
+
213
+ if reflection.through_reflection != through_reflection
214
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
215
+ end
216
+ end
217
+ end
218
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
219
+ if records.first.class.name !~ /^HABTM_/
220
+ if records.size > 1
221
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
222
+ Bullet::Detector::CounterCache.add_possible_objects(records)
223
+ elsif records.size == 1
224
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
225
+ Bullet::Detector::CounterCache.add_impossible_object(records.first)
226
+ end
227
+ end
228
+ end
229
+ records
230
+ end
231
+
232
+ def empty?
233
+ if Bullet.start? && !reflection.has_cached_counter?
234
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
235
+ end
236
+ super
237
+ end
238
+
239
+ def include?(object)
240
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
241
+ super
242
+ end
243
+ end
244
+ )
245
+
246
+ ::ActiveRecord::Associations::SingularAssociation.prepend(
247
+ Module.new do
248
+ # call has_one and belongs_to associations
249
+ def reader
250
+ result = super
251
+
252
+ if Bullet.start?
253
+ if owner.class.name !~ /^HABTM_/
254
+ if is_a? ::ActiveRecord::Associations::ThroughAssociation
255
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
256
+ association = owner.association(reflection.through_reflection.name)
257
+ Array.wrap(association.target).each do |through_record|
258
+ Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
259
+ end
260
+
261
+ if reflection.through_reflection != through_reflection
262
+ Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
263
+ end
264
+ end
265
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
266
+
267
+ if Bullet::Detector::NPlusOneQuery.impossible?(owner)
268
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
269
+ else
270
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
271
+ end
272
+ end
273
+ end
274
+ result
275
+ end
276
+ end
277
+ )
278
+
279
+ ::ActiveRecord::Associations::HasManyAssociation.prepend(
280
+ Module.new do
281
+ def empty?
282
+ result = super
283
+ if Bullet.start? && !reflection.has_cached_counter?
284
+ Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
285
+ end
286
+ result
287
+ end
288
+
289
+ def count_records
290
+ result = reflection.has_cached_counter?
291
+ if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
292
+ Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
293
+ end
294
+ super
295
+ end
296
+ end
297
+ )
298
+
299
+ ::ActiveRecord::Associations::CollectionProxy.prepend(
300
+ Module.new do
301
+ def count(column_name = nil)
302
+ if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
303
+ Bullet::Detector::CounterCache.add_counter_cache(
304
+ proxy_association.owner,
305
+ proxy_association.reflection.name
306
+ )
307
+ Bullet::Detector::NPlusOneQuery.call_association(
308
+ proxy_association.owner,
309
+ proxy_association.reflection.name
310
+ )
311
+ end
312
+ super(column_name)
313
+ end
314
+ end
315
+ )
316
+ end
317
+ end
318
+ end
@@ -31,6 +31,8 @@ module Bullet
31
31
  'active_record61'
32
32
  elsif active_record70?
33
33
  'active_record70'
34
+ elsif active_record71?
35
+ 'active_record71'
34
36
  else
35
37
  raise "Bullet does not support active_record #{::ActiveRecord::VERSION::STRING} yet"
36
38
  end
@@ -48,6 +50,8 @@ module Bullet
48
50
  'mongoid6x'
49
51
  elsif mongoid7x?
50
52
  'mongoid7x'
53
+ elsif mongoid8x?
54
+ 'mongoid8x'
51
55
  else
52
56
  raise "Bullet does not support mongoid #{::Mongoid::VERSION} yet"
53
57
  end
@@ -106,6 +110,10 @@ module Bullet
106
110
  active_record7? && ::ActiveRecord::VERSION::MINOR == 0
107
111
  end
108
112
 
113
+ def active_record71?
114
+ active_record7? && ::ActiveRecord::VERSION::MINOR == 1
115
+ end
116
+
109
117
  def mongoid4x?
110
118
  mongoid? && ::Mongoid::VERSION =~ /\A4/
111
119
  end
@@ -121,5 +129,9 @@ module Bullet
121
129
  def mongoid7x?
122
130
  mongoid? && ::Mongoid::VERSION =~ /\A7/
123
131
  end
132
+
133
+ def mongoid8x?
134
+ mongoid? && ::Mongoid::VERSION =~ /\A8/
135
+ end
124
136
  end
125
137
  end
@@ -44,13 +44,10 @@ module Bullet
44
44
  unless obj.bullet_primary_key_value.nil?
45
45
  primary_key_values_are_empty = false
46
46
  end
47
- keys_joined += "#{(keys_joined.empty?? '' : ', ')}#{obj.bullet_key}"
47
+ keys_joined += "#{(keys_joined.empty? ? '' : ', ')}#{obj.bullet_key}"
48
48
  end
49
49
  unless class_names_match_regex || primary_key_values_are_empty
50
- Bullet.debug(
51
- 'Detector::NPlusOneQuery#add_possible_objects',
52
- "objects: #{keys_joined}"
53
- )
50
+ Bullet.debug('Detector::NPlusOneQuery#add_possible_objects', "objects: #{keys_joined}")
54
51
  objects.each { |object| possible_objects.add object.bullet_key }
55
52
  end
56
53
  end
@@ -10,7 +10,7 @@ module Bullet
10
10
  # check if there are unused preload associations.
11
11
  # get related_objects from eager_loadings associated with object and associations
12
12
  # get call_object_association from associations of call_object_associations whose object is in related_objects
13
- # if association not in call_object_association, then the object => association - call_object_association is ununsed preload associations
13
+ # if association not in call_object_association, then the object => association - call_object_association is unused preload associations
14
14
  def check_unused_preload_associations
15
15
  return unless Bullet.start?
16
16
  return unless Bullet.unused_eager_loading_enable?
@@ -65,7 +65,10 @@ module Bullet
65
65
  private
66
66
 
67
67
  def create_notification(callers, klazz, associations)
68
- notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:unused_eager_loading, klazz)
68
+ notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(
69
+ :unused_eager_loading,
70
+ klazz
71
+ )
69
72
 
70
73
  if notify_associations.present?
71
74
  notice = Bullet::Notification::UnusedEagerLoading.new(callers, klazz, notify_associations)
@@ -9,11 +9,22 @@ class Object
9
9
  return if respond_to?(:persisted?) && !persisted?
10
10
 
11
11
  if self.class.respond_to?(:primary_keys) && self.class.primary_keys
12
- self.class.primary_keys.map { |primary_key| send primary_key }.join(',')
12
+ primary_key = self.class.primary_keys
13
13
  elsif self.class.respond_to?(:primary_key) && self.class.primary_key
14
- send self.class.primary_key
14
+ primary_key = self.class.primary_key
15
15
  else
16
- id
16
+ primary_key = :id
17
17
  end
18
+
19
+ bullet_join_potential_composite_primary_key(primary_key)
20
+ end
21
+
22
+ private
23
+
24
+ def bullet_join_potential_composite_primary_key(primary_keys)
25
+ return send(primary_keys) unless primary_keys.is_a?(Enumerable)
26
+
27
+ primary_keys.map { |primary_key| send primary_key }
28
+ .join(',')
18
29
  end
19
30
  end
@@ -0,0 +1,59 @@
1
+ module Bullet
2
+ module Mongoid
3
+ def self.enable
4
+ require 'mongoid'
5
+ ::Mongoid::Contextual::Mongo.class_eval do
6
+ alias_method :origin_first, :first
7
+ alias_method :origin_last, :last
8
+ alias_method :origin_each, :each
9
+ alias_method :origin_eager_load, :eager_load
10
+
11
+ def first(limit = nil)
12
+ result = origin_first(limit)
13
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
14
+ result
15
+ end
16
+
17
+ def last(limit = nil)
18
+ result = origin_last(limit)
19
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
20
+ result
21
+ end
22
+
23
+ def each(&block)
24
+ return to_enum unless block_given?
25
+
26
+ records = []
27
+ origin_each { |record| records << record }
28
+ if records.length > 1
29
+ Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
30
+ elsif records.size == 1
31
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
32
+ end
33
+ records.each(&block)
34
+ end
35
+
36
+ def eager_load(docs)
37
+ associations = criteria.inclusions.map(&:name)
38
+ docs.each do |doc|
39
+ Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations)
40
+ end
41
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
42
+ origin_eager_load(docs)
43
+ end
44
+ end
45
+
46
+ ::Mongoid::Association::Accessors.class_eval do
47
+ alias_method :origin_get_relation, :get_relation
48
+
49
+ def get_relation(name, association, object, reload = false)
50
+ result = origin_get_relation(name, association, object, reload)
51
+ unless association.embedded?
52
+ Bullet::Detector::NPlusOneQuery.call_association(self, name)
53
+ end
54
+ result
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -28,13 +28,13 @@ module Bullet
28
28
  def whoami
29
29
  @user ||=
30
30
  ENV['USER'].presence ||
31
- (
32
- begin
33
- `whoami`.chomp
34
- rescue StandardError
35
- ''
36
- end
37
- )
31
+ (
32
+ begin
33
+ `whoami`.chomp
34
+ rescue StandardError
35
+ ''
36
+ end
37
+ )
38
38
  @user.present? ? "user: #{@user}" : ''
39
39
  end
40
40
 
@@ -51,11 +51,22 @@ module Bullet
51
51
  end
52
52
 
53
53
  def short_notice
54
- [whoami.presence, url, title, body].compact.join(' ')
54
+ parts = []
55
+ parts << whoami.presence unless Bullet.skip_user_in_notification
56
+ parts << url
57
+ parts << title
58
+ parts << body
59
+
60
+ parts.compact.join(' ')
55
61
  end
56
62
 
57
63
  def notification_data
58
- { user: whoami, url: url, title: title, body: body_with_caller }
64
+ hash = {}
65
+ hash[:user] = whoami unless Bullet.skip_user_in_notification
66
+ hash[:url] = url
67
+ hash[:title] = title
68
+ hash[:body] = body_with_caller
69
+ hash
59
70
  end
60
71
 
61
72
  def eql?(other)
@@ -73,7 +84,8 @@ module Bullet
73
84
  end
74
85
 
75
86
  def associations_str
76
- ".includes(#{@associations.map { |a| a.to_s.to_sym }.inspect})"
87
+ ".includes(#{@associations.map { |a| a.to_s.to_sym }
88
+ .inspect})"
77
89
  end
78
90
  end
79
91
  end
@@ -8,7 +8,7 @@ module Bullet
8
8
  end
9
9
 
10
10
  def title
11
- 'Need Counter Cache'
11
+ 'Need Counter Cache with Active Record size'
12
12
  end
13
13
  end
14
14
  end