bullet 6.1.0 → 7.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +101 -2
- data/MIT-LICENSE +1 -1
- data/README.md +48 -30
- data/lib/bullet/active_job.rb +5 -1
- data/lib/bullet/active_record4.rb +21 -6
- data/lib/bullet/active_record41.rb +22 -6
- data/lib/bullet/active_record42.rb +33 -12
- data/lib/bullet/active_record5.rb +50 -20
- data/lib/bullet/active_record52.rb +71 -36
- data/lib/bullet/active_record60.rb +70 -35
- data/lib/bullet/active_record61.rb +302 -0
- data/lib/bullet/active_record70.rb +318 -0
- data/lib/bullet/active_record71.rb +318 -0
- data/lib/bullet/bullet_xhr.js +18 -17
- data/lib/bullet/dependency.rb +28 -0
- data/lib/bullet/detector/association.rb +8 -0
- data/lib/bullet/detector/base.rb +2 -1
- data/lib/bullet/detector/counter_cache.rb +2 -2
- data/lib/bullet/detector/n_plus_one_query.rb +21 -13
- data/lib/bullet/detector/unused_eager_loading.rb +6 -3
- data/lib/bullet/ext/object.rb +14 -3
- data/lib/bullet/mongoid4x.rb +1 -1
- data/lib/bullet/mongoid5x.rb +1 -1
- data/lib/bullet/mongoid6x.rb +1 -1
- data/lib/bullet/mongoid7x.rb +32 -17
- data/lib/bullet/mongoid8x.rb +59 -0
- data/lib/bullet/notification/base.rb +22 -10
- data/lib/bullet/notification/counter_cache.rb +1 -1
- data/lib/bullet/notification.rb +2 -1
- data/lib/bullet/rack.rb +67 -24
- data/lib/bullet/registry/association.rb +2 -1
- data/lib/bullet/registry/call_stack.rb +12 -0
- data/lib/bullet/registry.rb +1 -0
- data/lib/bullet/stack_trace_filter.rb +16 -15
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +45 -30
- data/lib/generators/bullet/install_generator.rb +22 -25
- metadata +13 -148
- data/.gitignore +0 -15
- data/.rspec +0 -2
- data/.travis.yml +0 -33
- data/Gemfile +0 -24
- data/Gemfile.mongoid +0 -12
- data/Gemfile.mongoid-4.0 +0 -15
- data/Gemfile.mongoid-5.0 +0 -15
- data/Gemfile.mongoid-6.0 +0 -15
- data/Gemfile.mongoid-7.0 +0 -15
- data/Gemfile.rails-4.0 +0 -16
- data/Gemfile.rails-4.1 +0 -16
- data/Gemfile.rails-4.2 +0 -16
- data/Gemfile.rails-5.0 +0 -15
- data/Gemfile.rails-5.1 +0 -15
- data/Gemfile.rails-5.2 +0 -15
- data/Gemfile.rails-6.0 +0 -15
- data/Guardfile +0 -8
- data/Hacking.md +0 -75
- data/Rakefile +0 -51
- data/bullet.gemspec +0 -33
- data/perf/benchmark.rb +0 -115
- data/rails/init.rb +0 -3
- data/spec/bullet/detector/association_spec.rb +0 -28
- data/spec/bullet/detector/base_spec.rb +0 -10
- data/spec/bullet/detector/counter_cache_spec.rb +0 -58
- data/spec/bullet/detector/n_plus_one_query_spec.rb +0 -182
- data/spec/bullet/detector/unused_eager_loading_spec.rb +0 -121
- data/spec/bullet/ext/object_spec.rb +0 -44
- data/spec/bullet/ext/string_spec.rb +0 -15
- data/spec/bullet/notification/base_spec.rb +0 -94
- data/spec/bullet/notification/counter_cache_spec.rb +0 -14
- data/spec/bullet/notification/n_plus_one_query_spec.rb +0 -31
- data/spec/bullet/notification/unused_eager_loading_spec.rb +0 -18
- data/spec/bullet/notification_collector_spec.rb +0 -34
- data/spec/bullet/rack_spec.rb +0 -153
- data/spec/bullet/registry/association_spec.rb +0 -28
- data/spec/bullet/registry/base_spec.rb +0 -46
- data/spec/bullet/registry/object_spec.rb +0 -26
- data/spec/bullet_spec.rb +0 -136
- data/spec/integration/active_record/association_spec.rb +0 -739
- data/spec/integration/counter_cache_spec.rb +0 -68
- data/spec/integration/mongoid/association_spec.rb +0 -246
- data/spec/models/address.rb +0 -5
- data/spec/models/author.rb +0 -5
- data/spec/models/base_user.rb +0 -7
- data/spec/models/category.rb +0 -12
- data/spec/models/city.rb +0 -5
- data/spec/models/client.rb +0 -8
- data/spec/models/comment.rb +0 -8
- data/spec/models/company.rb +0 -5
- data/spec/models/country.rb +0 -5
- data/spec/models/document.rb +0 -7
- data/spec/models/entry.rb +0 -5
- data/spec/models/firm.rb +0 -7
- data/spec/models/folder.rb +0 -3
- data/spec/models/group.rb +0 -3
- data/spec/models/mongoid/address.rb +0 -9
- data/spec/models/mongoid/category.rb +0 -10
- data/spec/models/mongoid/comment.rb +0 -9
- data/spec/models/mongoid/company.rb +0 -9
- data/spec/models/mongoid/entry.rb +0 -9
- data/spec/models/mongoid/post.rb +0 -14
- data/spec/models/mongoid/user.rb +0 -7
- data/spec/models/newspaper.rb +0 -5
- data/spec/models/page.rb +0 -3
- data/spec/models/person.rb +0 -5
- data/spec/models/pet.rb +0 -5
- data/spec/models/post.rb +0 -32
- data/spec/models/relationship.rb +0 -6
- data/spec/models/reply.rb +0 -5
- data/spec/models/student.rb +0 -5
- data/spec/models/submission.rb +0 -6
- data/spec/models/teacher.rb +0 -5
- data/spec/models/user.rb +0 -6
- data/spec/models/writer.rb +0 -3
- data/spec/spec_helper.rb +0 -99
- data/spec/support/bullet_ext.rb +0 -56
- data/spec/support/mongo_seed.rb +0 -58
- data/spec/support/rack_double.rb +0 -49
- data/spec/support/sqlite_seed.rb +0 -246
- data/test.sh +0 -13
- data/update.sh +0 -10
data/lib/bullet/bullet_xhr.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
(function() {
|
1
|
+
(function () {
|
2
2
|
var oldOpen = window.XMLHttpRequest.prototype.open;
|
3
3
|
var oldSend = window.XMLHttpRequest.prototype.send;
|
4
4
|
|
@@ -10,41 +10,42 @@
|
|
10
10
|
if (isBulletInitiated()) return;
|
11
11
|
|
12
12
|
function isBulletInitiated() {
|
13
|
-
return oldOpen.name ==
|
13
|
+
return oldOpen.name == "bulletXHROpen" && oldSend.name == "bulletXHRSend";
|
14
14
|
}
|
15
15
|
function bulletXHROpen(_, url) {
|
16
16
|
this._storedUrl = url;
|
17
|
-
return
|
17
|
+
return Reflect.apply(oldOpen, this, arguments);
|
18
18
|
}
|
19
19
|
function bulletXHRSend() {
|
20
20
|
if (this.onload) {
|
21
21
|
this._storedOnload = this.onload;
|
22
22
|
}
|
23
|
-
this.
|
24
|
-
|
23
|
+
this.onload = null;
|
24
|
+
this.addEventListener("load", bulletXHROnload);
|
25
|
+
return Reflect.apply(oldSend, this, arguments);
|
25
26
|
}
|
26
27
|
function bulletXHROnload() {
|
27
28
|
if (
|
28
|
-
this._storedUrl.startsWith(window.location.protocol +
|
29
|
-
!this._storedUrl.startsWith(
|
29
|
+
this._storedUrl.startsWith(window.location.protocol + "//" + window.location.host) ||
|
30
|
+
!this._storedUrl.startsWith("http") // For relative paths
|
30
31
|
) {
|
31
|
-
var bulletFooterText = this.getResponseHeader(
|
32
|
+
var bulletFooterText = this.getResponseHeader("X-bullet-footer-text");
|
32
33
|
if (bulletFooterText) {
|
33
|
-
setTimeout(()
|
34
|
-
var oldHtml = document.
|
34
|
+
setTimeout(function () {
|
35
|
+
var oldHtml = document.querySelector("#bullet-footer").innerHTML.split("<br>");
|
35
36
|
var header = oldHtml[0];
|
36
37
|
oldHtml = oldHtml.slice(1, oldHtml.length);
|
37
38
|
var newHtml = oldHtml.concat(JSON.parse(bulletFooterText));
|
38
39
|
newHtml = newHtml.slice(newHtml.length - 10, newHtml.length); // rotate through 10 most recent
|
39
|
-
document.
|
40
|
+
document.querySelector("#bullet-footer").innerHTML = `${header}<br>${newHtml.join("<br>")}`;
|
40
41
|
}, 0);
|
41
42
|
}
|
42
|
-
var bulletConsoleText = this.getResponseHeader(
|
43
|
-
if (bulletConsoleText && typeof console !==
|
44
|
-
setTimeout(()
|
45
|
-
JSON.parse(bulletConsoleText).forEach(message => {
|
43
|
+
var bulletConsoleText = this.getResponseHeader("X-bullet-console-text");
|
44
|
+
if (bulletConsoleText && typeof console !== "undefined" && console.log) {
|
45
|
+
setTimeout(function () {
|
46
|
+
JSON.parse(bulletConsoleText).forEach((message) => {
|
46
47
|
if (console.groupCollapsed && console.groupEnd) {
|
47
|
-
console.groupCollapsed(
|
48
|
+
console.groupCollapsed("Uniform Notifier");
|
48
49
|
console.log(message);
|
49
50
|
console.groupEnd();
|
50
51
|
} else {
|
@@ -55,7 +56,7 @@
|
|
55
56
|
}
|
56
57
|
}
|
57
58
|
if (this._storedOnload) {
|
58
|
-
return
|
59
|
+
return Reflect.apply(this._storedOnload, this, arguments);
|
59
60
|
}
|
60
61
|
}
|
61
62
|
window.XMLHttpRequest.prototype.open = bulletXHROpen;
|
data/lib/bullet/dependency.rb
CHANGED
@@ -27,6 +27,12 @@ module Bullet
|
|
27
27
|
'active_record52'
|
28
28
|
elsif active_record60?
|
29
29
|
'active_record60'
|
30
|
+
elsif active_record61?
|
31
|
+
'active_record61'
|
32
|
+
elsif active_record70?
|
33
|
+
'active_record70'
|
34
|
+
elsif active_record71?
|
35
|
+
'active_record71'
|
30
36
|
else
|
31
37
|
raise "Bullet does not support active_record #{::ActiveRecord::VERSION::STRING} yet"
|
32
38
|
end
|
@@ -44,6 +50,8 @@ module Bullet
|
|
44
50
|
'mongoid6x'
|
45
51
|
elsif mongoid7x?
|
46
52
|
'mongoid7x'
|
53
|
+
elsif mongoid8x?
|
54
|
+
'mongoid8x'
|
47
55
|
else
|
48
56
|
raise "Bullet does not support mongoid #{::Mongoid::VERSION} yet"
|
49
57
|
end
|
@@ -62,6 +70,10 @@ module Bullet
|
|
62
70
|
active_record? && ::ActiveRecord::VERSION::MAJOR == 6
|
63
71
|
end
|
64
72
|
|
73
|
+
def active_record7?
|
74
|
+
active_record? && ::ActiveRecord::VERSION::MAJOR == 7
|
75
|
+
end
|
76
|
+
|
65
77
|
def active_record40?
|
66
78
|
active_record4? && ::ActiveRecord::VERSION::MINOR == 0
|
67
79
|
end
|
@@ -90,6 +102,18 @@ module Bullet
|
|
90
102
|
active_record6? && ::ActiveRecord::VERSION::MINOR == 0
|
91
103
|
end
|
92
104
|
|
105
|
+
def active_record61?
|
106
|
+
active_record6? && ::ActiveRecord::VERSION::MINOR == 1
|
107
|
+
end
|
108
|
+
|
109
|
+
def active_record70?
|
110
|
+
active_record7? && ::ActiveRecord::VERSION::MINOR == 0
|
111
|
+
end
|
112
|
+
|
113
|
+
def active_record71?
|
114
|
+
active_record7? && ::ActiveRecord::VERSION::MINOR == 1
|
115
|
+
end
|
116
|
+
|
93
117
|
def mongoid4x?
|
94
118
|
mongoid? && ::Mongoid::VERSION =~ /\A4/
|
95
119
|
end
|
@@ -105,5 +129,9 @@ module Bullet
|
|
105
129
|
def mongoid7x?
|
106
130
|
mongoid? && ::Mongoid::VERSION =~ /\A7/
|
107
131
|
end
|
132
|
+
|
133
|
+
def mongoid8x?
|
134
|
+
mongoid? && ::Mongoid::VERSION =~ /\A8/
|
135
|
+
end
|
108
136
|
end
|
109
137
|
end
|
@@ -13,6 +13,7 @@ module Bullet
|
|
13
13
|
'Detector::Association#add_object_associations',
|
14
14
|
"object: #{object.bullet_key}, associations: #{associations}"
|
15
15
|
)
|
16
|
+
call_stacks.add(object.bullet_key)
|
16
17
|
object_associations.add(object.bullet_key, associations)
|
17
18
|
end
|
18
19
|
|
@@ -25,6 +26,7 @@ module Bullet
|
|
25
26
|
'Detector::Association#add_call_object_associations',
|
26
27
|
"object: #{object.bullet_key}, associations: #{associations}"
|
27
28
|
)
|
29
|
+
call_stacks.add(object.bullet_key)
|
28
30
|
call_object_associations.add(object.bullet_key, associations)
|
29
31
|
end
|
30
32
|
|
@@ -76,6 +78,12 @@ module Bullet
|
|
76
78
|
def eager_loadings
|
77
79
|
Thread.current[:bullet_eager_loadings]
|
78
80
|
end
|
81
|
+
|
82
|
+
# cal_stacks keeps stacktraces where querie-objects were called from.
|
83
|
+
# e.g. { 'Object:111' => [SomeProject/app/controllers/...] }
|
84
|
+
def call_stacks
|
85
|
+
Thread.current[:bullet_call_stacks]
|
86
|
+
end
|
79
87
|
end
|
80
88
|
end
|
81
89
|
end
|
data/lib/bullet/detector/base.rb
CHANGED
@@ -20,7 +20,7 @@ module Bullet
|
|
20
20
|
return unless Bullet.start?
|
21
21
|
return unless Bullet.counter_cache_enable?
|
22
22
|
|
23
|
-
objects = Array(object_or_objects)
|
23
|
+
objects = Array.wrap(object_or_objects)
|
24
24
|
return if objects.map(&:bullet_primary_key_value).compact.empty?
|
25
25
|
|
26
26
|
Bullet.debug(
|
@@ -54,7 +54,7 @@ module Bullet
|
|
54
54
|
private
|
55
55
|
|
56
56
|
def create_notification(klazz, associations)
|
57
|
-
notify_associations = Array(associations) - Bullet.
|
57
|
+
notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:counter_cache, klazz)
|
58
58
|
|
59
59
|
if notify_associations.present?
|
60
60
|
notice = Bullet::Notification::CounterCache.new klazz, notify_associations
|
@@ -7,7 +7,7 @@ module Bullet
|
|
7
7
|
extend StackTraceFilter
|
8
8
|
|
9
9
|
class << self
|
10
|
-
# executed when object.
|
10
|
+
# executed when object.associations is called.
|
11
11
|
# first, it keeps this method call for object.association.
|
12
12
|
# then, it checks if this associations call is unpreload.
|
13
13
|
# if it is, keeps this unpreload associations and caller.
|
@@ -25,7 +25,7 @@ module Bullet
|
|
25
25
|
)
|
26
26
|
if !excluded_stacktrace_path? && conditions_met?(object, associations)
|
27
27
|
Bullet.debug('detect n + 1 query', "object: #{object.bullet_key}, associations: #{associations}")
|
28
|
-
create_notification caller_in_project, object.class.to_s, associations
|
28
|
+
create_notification caller_in_project(object.bullet_key), object.class.to_s, associations
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -33,14 +33,23 @@ module Bullet
|
|
33
33
|
return unless Bullet.start?
|
34
34
|
return unless Bullet.n_plus_one_query_enable?
|
35
35
|
|
36
|
-
objects = Array(object_or_objects)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
36
|
+
objects = Array.wrap(object_or_objects)
|
37
|
+
class_names_match_regex = true
|
38
|
+
primary_key_values_are_empty = true
|
39
|
+
keys_joined = ""
|
40
|
+
objects.each do |obj|
|
41
|
+
unless obj.class.name =~ /^HABTM_/
|
42
|
+
class_names_match_regex = false
|
43
|
+
end
|
44
|
+
unless obj.bullet_primary_key_value.nil?
|
45
|
+
primary_key_values_are_empty = false
|
46
|
+
end
|
47
|
+
keys_joined += "#{(keys_joined.empty? ? '' : ', ')}#{obj.bullet_key}"
|
48
|
+
end
|
49
|
+
unless class_names_match_regex || primary_key_values_are_empty
|
50
|
+
Bullet.debug('Detector::NPlusOneQuery#add_possible_objects', "objects: #{keys_joined}")
|
51
|
+
objects.each { |object| possible_objects.add object.bullet_key }
|
52
|
+
end
|
44
53
|
end
|
45
54
|
|
46
55
|
def add_impossible_object(object)
|
@@ -84,8 +93,7 @@ module Bullet
|
|
84
93
|
# associations == v comparison order is important here because
|
85
94
|
# v variable might be a squeel node where :== method is redefined,
|
86
95
|
# so it does not compare values at all and return unexpected results
|
87
|
-
result =
|
88
|
-
v.is_a?(Hash) ? v.key?(associations) : associations == v
|
96
|
+
result = v.is_a?(Hash) ? v.key?(associations) : associations == v
|
89
97
|
return true if result
|
90
98
|
end
|
91
99
|
|
@@ -95,7 +103,7 @@ module Bullet
|
|
95
103
|
private
|
96
104
|
|
97
105
|
def create_notification(callers, klazz, associations)
|
98
|
-
notify_associations = Array(associations) - Bullet.
|
106
|
+
notify_associations = Array.wrap(associations) - Bullet.get_safelist_associations(:n_plus_one_query, klazz)
|
99
107
|
|
100
108
|
if notify_associations.present?
|
101
109
|
notice = Bullet::Notification::NPlusOneQuery.new(callers, klazz, notify_associations)
|
@@ -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
|
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?
|
@@ -20,7 +20,7 @@ module Bullet
|
|
20
20
|
next if object_association_diff.empty?
|
21
21
|
|
22
22
|
Bullet.debug('detect unused preload', "object: #{bullet_key}, associations: #{object_association_diff}")
|
23
|
-
create_notification(caller_in_project, bullet_key.bullet_class_name, object_association_diff)
|
23
|
+
create_notification(caller_in_project(bullet_key), bullet_key.bullet_class_name, object_association_diff)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -65,7 +65,10 @@ module Bullet
|
|
65
65
|
private
|
66
66
|
|
67
67
|
def create_notification(callers, klazz, associations)
|
68
|
-
notify_associations = Array(associations) - Bullet.
|
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)
|
data/lib/bullet/ext/object.rb
CHANGED
@@ -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
|
12
|
+
primary_key = self.class.primary_keys
|
13
13
|
elsif self.class.respond_to?(:primary_key) && self.class.primary_key
|
14
|
-
|
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
|
data/lib/bullet/mongoid4x.rb
CHANGED
data/lib/bullet/mongoid5x.rb
CHANGED
data/lib/bullet/mongoid6x.rb
CHANGED
data/lib/bullet/mongoid7x.rb
CHANGED
@@ -4,35 +4,50 @@ module Bullet
|
|
4
4
|
module Mongoid
|
5
5
|
def self.enable
|
6
6
|
require 'mongoid'
|
7
|
+
require 'rubygems'
|
7
8
|
::Mongoid::Contextual::Mongo.class_eval do
|
8
9
|
alias_method :origin_first, :first
|
9
10
|
alias_method :origin_last, :last
|
10
11
|
alias_method :origin_each, :each
|
11
12
|
alias_method :origin_eager_load, :eager_load
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
result = origin_last(opts)
|
21
|
-
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
22
|
-
result
|
14
|
+
%i[first last].each do |context|
|
15
|
+
default = Gem::Version.new(::Mongoid::VERSION) >= Gem::Version.new('7.5') ? nil : {}
|
16
|
+
define_method(context) do |opts = default|
|
17
|
+
result = send(:"origin_#{context}", opts)
|
18
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
19
|
+
result
|
20
|
+
end
|
23
21
|
end
|
24
22
|
|
25
23
|
def each(&block)
|
26
24
|
return to_enum unless block_given?
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
26
|
+
first_document = nil
|
27
|
+
document_count = 0
|
28
|
+
|
29
|
+
origin_each do |document|
|
30
|
+
document_count += 1
|
31
|
+
|
32
|
+
if document_count == 1
|
33
|
+
first_document = document
|
34
|
+
elsif document_count == 2
|
35
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects([first_document, document])
|
36
|
+
yield(first_document)
|
37
|
+
first_document = nil
|
38
|
+
yield(document)
|
39
|
+
else
|
40
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(document)
|
41
|
+
yield(document)
|
42
|
+
end
|
34
43
|
end
|
35
|
-
|
44
|
+
|
45
|
+
if document_count == 1
|
46
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(first_document)
|
47
|
+
yield(first_document)
|
48
|
+
end
|
49
|
+
|
50
|
+
self
|
36
51
|
end
|
37
52
|
|
38
53
|
def eager_load(docs)
|
@@ -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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
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
|
-
|
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 }
|
87
|
+
".includes(#{@associations.map { |a| a.to_s.to_sym }
|
88
|
+
.inspect})"
|
77
89
|
end
|
78
90
|
end
|
79
91
|
end
|
data/lib/bullet/notification.rb
CHANGED