bullet 5.9.0 → 7.0.4
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 +5 -5
- data/.github/workflows/main.yml +82 -0
- data/CHANGELOG.md +72 -0
- data/Gemfile.rails-4.0 +1 -1
- data/Gemfile.rails-4.1 +1 -1
- data/Gemfile.rails-4.2 +1 -1
- data/Gemfile.rails-5.0 +1 -1
- data/Gemfile.rails-5.1 +1 -1
- data/Gemfile.rails-5.2 +1 -1
- data/Gemfile.rails-6.0 +15 -0
- data/Gemfile.rails-6.1 +15 -0
- data/Gemfile.rails-7.0 +10 -0
- data/MIT-LICENSE +1 -1
- data/README.md +59 -33
- data/lib/bullet/active_job.rb +13 -0
- data/lib/bullet/active_record4.rb +9 -32
- data/lib/bullet/active_record41.rb +8 -27
- data/lib/bullet/active_record42.rb +9 -24
- data/lib/bullet/active_record5.rb +190 -179
- data/lib/bullet/active_record52.rb +184 -169
- data/lib/bullet/active_record60.rb +274 -0
- data/lib/bullet/active_record61.rb +274 -0
- data/lib/bullet/active_record70.rb +277 -0
- data/lib/bullet/bullet_xhr.js +64 -0
- data/lib/bullet/dependency.rb +60 -36
- data/lib/bullet/detector/association.rb +26 -20
- data/lib/bullet/detector/counter_cache.rb +15 -11
- data/lib/bullet/detector/n_plus_one_query.rb +24 -14
- data/lib/bullet/detector/unused_eager_loading.rb +8 -5
- data/lib/bullet/ext/object.rb +4 -2
- data/lib/bullet/mongoid4x.rb +3 -7
- data/lib/bullet/mongoid5x.rb +3 -7
- data/lib/bullet/mongoid6x.rb +3 -7
- data/lib/bullet/mongoid7x.rb +34 -23
- data/lib/bullet/notification/base.rb +14 -18
- data/lib/bullet/notification/n_plus_one_query.rb +2 -4
- data/lib/bullet/notification/unused_eager_loading.rb +2 -4
- data/lib/bullet/notification.rb +2 -1
- data/lib/bullet/rack.rb +55 -27
- data/lib/bullet/stack_trace_filter.rb +11 -19
- data/lib/bullet/version.rb +1 -1
- data/lib/bullet.rb +68 -42
- data/lib/generators/bullet/install_generator.rb +22 -23
- data/perf/benchmark.rb +11 -14
- data/spec/bullet/detector/counter_cache_spec.rb +6 -6
- data/spec/bullet/detector/n_plus_one_query_spec.rb +8 -4
- data/spec/bullet/detector/unused_eager_loading_spec.rb +25 -8
- data/spec/bullet/ext/object_spec.rb +10 -5
- data/spec/bullet/notification/base_spec.rb +5 -7
- data/spec/bullet/notification/n_plus_one_query_spec.rb +16 -3
- data/spec/bullet/notification/unused_eager_loading_spec.rb +5 -1
- data/spec/bullet/rack_spec.rb +161 -11
- data/spec/bullet/registry/association_spec.rb +2 -2
- data/spec/bullet/registry/base_spec.rb +1 -1
- data/spec/bullet_spec.rb +25 -44
- data/spec/integration/active_record/association_spec.rb +115 -144
- data/spec/integration/counter_cache_spec.rb +14 -34
- data/spec/integration/mongoid/association_spec.rb +19 -33
- data/spec/models/attachment.rb +5 -0
- data/spec/models/deal.rb +5 -0
- data/spec/models/post.rb +2 -0
- data/spec/models/role.rb +7 -0
- data/spec/models/submission.rb +1 -0
- data/spec/models/user.rb +2 -0
- data/spec/spec_helper.rb +4 -10
- data/spec/support/bullet_ext.rb +8 -9
- data/spec/support/mongo_seed.rb +3 -16
- data/spec/support/sqlite_seed.rb +38 -0
- data/test.sh +3 -0
- metadata +21 -8
- data/.travis.yml +0 -12
data/lib/bullet.rb
CHANGED
@@ -14,15 +14,13 @@ module Bullet
|
|
14
14
|
autoload :ActiveRecord, "bullet/#{active_record_version}" if active_record?
|
15
15
|
autoload :Mongoid, "bullet/#{mongoid_version}" if mongoid?
|
16
16
|
autoload :Rack, 'bullet/rack'
|
17
|
+
autoload :ActiveJob, 'bullet/active_job'
|
17
18
|
autoload :Notification, 'bullet/notification'
|
18
19
|
autoload :Detector, 'bullet/detector'
|
19
20
|
autoload :Registry, 'bullet/registry'
|
20
21
|
autoload :NotificationCollector, 'bullet/notification_collector'
|
21
22
|
|
22
|
-
|
23
|
-
TRUE = 'true'
|
24
|
-
|
25
|
-
if defined? Rails::Railtie
|
23
|
+
if defined?(Rails::Railtie)
|
26
24
|
class BulletRailtie < Rails::Railtie
|
27
25
|
initializer 'bullet.configure_rails_initialization' do |app|
|
28
26
|
app.middleware.use Bullet::Rack
|
@@ -31,28 +29,37 @@ module Bullet
|
|
31
29
|
end
|
32
30
|
|
33
31
|
class << self
|
34
|
-
attr_writer :n_plus_one_query_enable,
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
32
|
+
attr_writer :n_plus_one_query_enable,
|
33
|
+
:unused_eager_loading_enable,
|
34
|
+
:counter_cache_enable,
|
35
|
+
:stacktrace_includes,
|
36
|
+
:stacktrace_excludes,
|
37
|
+
:skip_html_injection
|
38
|
+
attr_reader :safelist
|
39
|
+
attr_accessor :add_footer, :orm_patches_applied, :skip_http_headers
|
40
|
+
|
41
|
+
available_notifiers =
|
42
|
+
UniformNotifier::AVAILABLE_NOTIFIERS.select { |notifier| notifier != :raise }.map { |notifier| "#{notifier}=" }
|
43
|
+
available_notifiers_options = { to: UniformNotifier }
|
44
|
+
delegate(*available_notifiers, **available_notifiers_options)
|
41
45
|
|
42
46
|
def raise=(should_raise)
|
43
47
|
UniformNotifier.raise = (should_raise ? Notification::UnoptimizedQueryError : false)
|
44
48
|
end
|
45
49
|
|
46
|
-
DETECTORS = [
|
47
|
-
|
48
|
-
|
50
|
+
DETECTORS = [
|
51
|
+
Bullet::Detector::NPlusOneQuery,
|
52
|
+
Bullet::Detector::UnusedEagerLoading,
|
53
|
+
Bullet::Detector::CounterCache
|
54
|
+
].freeze
|
49
55
|
|
50
56
|
def enable=(enable)
|
51
57
|
@enable = @n_plus_one_query_enable = @unused_eager_loading_enable = @counter_cache_enable = enable
|
58
|
+
|
52
59
|
if enable?
|
53
|
-
|
54
|
-
unless
|
55
|
-
self.
|
60
|
+
reset_safelist
|
61
|
+
unless orm_patches_applied
|
62
|
+
self.orm_patches_applied = true
|
56
63
|
Bullet::Mongoid.enable if mongoid?
|
57
64
|
Bullet::ActiveRecord.enable if active_record?
|
58
65
|
end
|
@@ -63,6 +70,11 @@ module Bullet
|
|
63
70
|
!!@enable
|
64
71
|
end
|
65
72
|
|
73
|
+
# Rails.root might be nil if `railties` is a dependency on a project that does not use Rails
|
74
|
+
def app_root
|
75
|
+
@app_root ||= (defined?(::Rails.root) && !::Rails.root.nil? ? Rails.root.to_s : Dir.pwd).to_s
|
76
|
+
end
|
77
|
+
|
66
78
|
def n_plus_one_query_enable?
|
67
79
|
enable? && !!@n_plus_one_query_enable
|
68
80
|
end
|
@@ -76,51 +88,50 @@ module Bullet
|
|
76
88
|
end
|
77
89
|
|
78
90
|
def stacktrace_includes
|
79
|
-
@stacktrace_includes
|
91
|
+
@stacktrace_includes ||= []
|
80
92
|
end
|
81
93
|
|
82
94
|
def stacktrace_excludes
|
83
|
-
@stacktrace_excludes
|
95
|
+
@stacktrace_excludes ||= []
|
84
96
|
end
|
85
97
|
|
86
|
-
def
|
87
|
-
|
88
|
-
@
|
89
|
-
@
|
98
|
+
def add_safelist(options)
|
99
|
+
reset_safelist
|
100
|
+
@safelist[options[:type]][options[:class_name]] ||= []
|
101
|
+
@safelist[options[:type]][options[:class_name]] << options[:association].to_sym
|
90
102
|
end
|
91
103
|
|
92
|
-
def
|
93
|
-
|
94
|
-
@
|
95
|
-
@
|
96
|
-
@
|
104
|
+
def delete_safelist(options)
|
105
|
+
reset_safelist
|
106
|
+
@safelist[options[:type]][options[:class_name]] ||= []
|
107
|
+
@safelist[options[:type]][options[:class_name]].delete(options[:association].to_sym)
|
108
|
+
@safelist[options[:type]].delete_if { |_key, val| val.empty? }
|
97
109
|
end
|
98
110
|
|
99
|
-
def
|
100
|
-
Array(@
|
111
|
+
def get_safelist_associations(type, class_name)
|
112
|
+
Array.wrap(@safelist[type][class_name])
|
101
113
|
end
|
102
114
|
|
103
|
-
def
|
104
|
-
@
|
115
|
+
def reset_safelist
|
116
|
+
@safelist ||= { n_plus_one_query: {}, unused_eager_loading: {}, counter_cache: {} }
|
105
117
|
end
|
106
118
|
|
107
|
-
def
|
108
|
-
@
|
119
|
+
def clear_safelist
|
120
|
+
@safelist = nil
|
109
121
|
end
|
110
122
|
|
111
123
|
def bullet_logger=(active)
|
112
124
|
if active
|
113
125
|
require 'fileutils'
|
114
|
-
|
115
|
-
|
116
|
-
bullet_log_file = File.open("#{root_path}/log/bullet.log", 'a+')
|
126
|
+
FileUtils.mkdir_p(app_root + '/log')
|
127
|
+
bullet_log_file = File.open("#{app_root}/log/bullet.log", 'a+')
|
117
128
|
bullet_log_file.sync = true
|
118
129
|
UniformNotifier.customized_logger = bullet_log_file
|
119
130
|
end
|
120
131
|
end
|
121
132
|
|
122
133
|
def debug(title, message)
|
123
|
-
puts "[Bullet][#{title}] #{message}" if ENV[BULLET_DEBUG] ==
|
134
|
+
puts "[Bullet][#{title}] #{message}" if ENV['BULLET_DEBUG'] == 'true'
|
124
135
|
end
|
125
136
|
|
126
137
|
def start_request
|
@@ -170,9 +181,7 @@ module Bullet
|
|
170
181
|
|
171
182
|
def gather_inline_notifications
|
172
183
|
responses = []
|
173
|
-
for_each_active_notifier_with_notification
|
174
|
-
responses << notification.notify_inline
|
175
|
-
end
|
184
|
+
for_each_active_notifier_with_notification { |notification| responses << notification.notify_inline }
|
176
185
|
responses.join("\n")
|
177
186
|
end
|
178
187
|
|
@@ -185,9 +194,15 @@ module Bullet
|
|
185
194
|
end
|
186
195
|
|
187
196
|
def footer_info
|
197
|
+
info = []
|
198
|
+
notification_collector.collection.each { |notification| info << notification.short_notice }
|
199
|
+
info
|
200
|
+
end
|
201
|
+
|
202
|
+
def text_notifications
|
188
203
|
info = []
|
189
204
|
notification_collector.collection.each do |notification|
|
190
|
-
info << notification.
|
205
|
+
info << notification.notification_data.values.compact.join("\n")
|
191
206
|
end
|
192
207
|
info
|
193
208
|
end
|
@@ -202,6 +217,7 @@ module Bullet
|
|
202
217
|
|
203
218
|
def profile
|
204
219
|
return_value = nil
|
220
|
+
|
205
221
|
if Bullet.enable?
|
206
222
|
begin
|
207
223
|
Bullet.start_request
|
@@ -219,6 +235,16 @@ module Bullet
|
|
219
235
|
return_value
|
220
236
|
end
|
221
237
|
|
238
|
+
def console_enabled?
|
239
|
+
UniformNotifier.active_notifiers.include?(UniformNotifier::JavascriptConsole)
|
240
|
+
end
|
241
|
+
|
242
|
+
def inject_into_page?
|
243
|
+
return false if defined?(@skip_html_injection) && @skip_html_injection
|
244
|
+
|
245
|
+
console_enabled? || add_footer
|
246
|
+
end
|
247
|
+
|
222
248
|
private
|
223
249
|
|
224
250
|
def for_each_active_notifier_with_notification
|
@@ -10,17 +10,16 @@ module Bullet
|
|
10
10
|
|
11
11
|
def enable_in_development
|
12
12
|
environment(nil, env: 'development') do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
13
|
+
<<~FILE
|
14
|
+
config.after_initialize do
|
15
|
+
Bullet.enable = true
|
16
|
+
Bullet.alert = true
|
17
|
+
Bullet.bullet_logger = true
|
18
|
+
Bullet.console = true
|
19
|
+
Bullet.rails_logger = true
|
20
|
+
Bullet.add_footer = true
|
21
|
+
end
|
22
|
+
|
24
23
|
FILE
|
25
24
|
end
|
26
25
|
|
@@ -28,20 +27,20 @@ module Bullet
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def enable_in_test
|
31
|
-
|
32
|
-
environment(nil, env: 'test') do
|
33
|
-
<<-"FILE".strip
|
34
|
-
|
35
|
-
config.after_initialize do
|
36
|
-
Bullet.enable = true
|
37
|
-
Bullet.bullet_logger = true
|
38
|
-
Bullet.raise = true # raise an error if n+1 query occurs
|
39
|
-
end
|
40
|
-
FILE
|
41
|
-
end
|
30
|
+
return unless yes?('Would you like to enable bullet in test environment? (y/n)')
|
42
31
|
|
43
|
-
|
32
|
+
environment(nil, env: 'test') do
|
33
|
+
<<~FILE
|
34
|
+
config.after_initialize do
|
35
|
+
Bullet.enable = true
|
36
|
+
Bullet.bullet_logger = true
|
37
|
+
Bullet.raise = true # raise an error if n+1 query occurs
|
38
|
+
end
|
39
|
+
|
40
|
+
FILE
|
44
41
|
end
|
42
|
+
|
43
|
+
say 'Enabled bullet in config/environments/test.rb'
|
45
44
|
end
|
46
45
|
end
|
47
46
|
end
|
data/perf/benchmark.rb
CHANGED
@@ -29,11 +29,14 @@ class User < ActiveRecord::Base
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# create database bullet_benchmark;
|
32
|
-
ActiveRecord::Base.establish_connection(
|
32
|
+
ActiveRecord::Base.establish_connection(
|
33
|
+
adapter: 'mysql2',
|
34
|
+
database: 'bullet_benchmark',
|
35
|
+
server: '/tmp/mysql.socket',
|
36
|
+
username: 'root'
|
37
|
+
)
|
33
38
|
|
34
|
-
ActiveRecord::Base.connection.tables.each
|
35
|
-
ActiveRecord::Base.connection.drop_table(table)
|
36
|
-
end
|
39
|
+
ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
37
40
|
|
38
41
|
ActiveRecord::Schema.define(version: 1) do
|
39
42
|
create_table :posts do |t|
|
@@ -54,26 +57,20 @@ ActiveRecord::Schema.define(version: 1) do
|
|
54
57
|
end
|
55
58
|
|
56
59
|
users_size = 100
|
57
|
-
posts_size =
|
60
|
+
posts_size = 1_000
|
58
61
|
comments_size = 10_000
|
59
62
|
users = []
|
60
|
-
users_size.times
|
61
|
-
users << User.new(name: "user#{i}")
|
62
|
-
end
|
63
|
+
users_size.times { |i| users << User.new(name: "user#{i}") }
|
63
64
|
User.import users
|
64
65
|
users = User.all
|
65
66
|
|
66
67
|
posts = []
|
67
|
-
posts_size.times
|
68
|
-
posts << Post.new(title: "Title #{i}", body: "Body #{i}", user: users[i % 100])
|
69
|
-
end
|
68
|
+
posts_size.times { |i| posts << Post.new(title: "Title #{i}", body: "Body #{i}", user: users[i % 100]) }
|
70
69
|
Post.import posts
|
71
70
|
posts = Post.all
|
72
71
|
|
73
72
|
comments = []
|
74
|
-
comments_size.times
|
75
|
-
comments << Comment.new(body: "Comment #{i}", post: posts[i % 1000], user: users[i % 100])
|
76
|
-
end
|
73
|
+
comments_size.times { |i| comments << Comment.new(body: "Comment #{i}", post: posts[i % 1_000], user: users[i % 100]) }
|
77
74
|
Comment.import comments
|
78
75
|
|
79
76
|
puts 'Start benchmarking...'
|
@@ -12,15 +12,15 @@ module Bullet
|
|
12
12
|
|
13
13
|
context '.add_counter_cache' do
|
14
14
|
it 'should create notification if conditions met' do
|
15
|
-
expect(CounterCache).to receive(:conditions_met?).with(@post1, [
|
16
|
-
expect(CounterCache).to receive(:create_notification).with('Post', [
|
17
|
-
CounterCache.add_counter_cache(@post1, [
|
15
|
+
expect(CounterCache).to receive(:conditions_met?).with(@post1, %i[comments]).and_return(true)
|
16
|
+
expect(CounterCache).to receive(:create_notification).with('Post', %i[comments])
|
17
|
+
CounterCache.add_counter_cache(@post1, %i[comments])
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should not create notification if conditions not met' do
|
21
|
-
expect(CounterCache).to receive(:conditions_met?).with(@post1, [
|
21
|
+
expect(CounterCache).to receive(:conditions_met?).with(@post1, %i[comments]).and_return(false)
|
22
22
|
expect(CounterCache).to receive(:create_notification).never
|
23
|
-
CounterCache.add_counter_cache(@post1, [
|
23
|
+
CounterCache.add_counter_cache(@post1, %i[comments])
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -47,7 +47,7 @@ module Bullet
|
|
47
47
|
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
48
48
|
end
|
49
49
|
|
50
|
-
it 'should be
|
50
|
+
it 'should be false when object is possible, and impossible' do
|
51
51
|
CounterCache.add_possible_objects(@post1)
|
52
52
|
CounterCache.add_impossible_object(@post1)
|
53
53
|
expect(CounterCache.conditions_met?(@post1, :associations)).to eq false
|
@@ -39,7 +39,7 @@ module Bullet
|
|
39
39
|
|
40
40
|
it 'should be false if object, association pair is not existed' do
|
41
41
|
NPlusOneQuery.add_object_associations(@post, :association1)
|
42
|
-
expect(NPlusOneQuery.association?(@post, :
|
42
|
+
expect(NPlusOneQuery.association?(@post, :association2)).to eq false
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -76,8 +76,8 @@ module Bullet
|
|
76
76
|
context '.call_association' do
|
77
77
|
it 'should create notification if conditions met' do
|
78
78
|
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
79
|
-
expect(NPlusOneQuery).to receive(:caller_in_project).and_return([
|
80
|
-
expect(NPlusOneQuery).to receive(:create_notification).with([
|
79
|
+
expect(NPlusOneQuery).to receive(:caller_in_project).and_return(%w[caller])
|
80
|
+
expect(NPlusOneQuery).to receive(:create_notification).with(%w[caller], 'Post', :association)
|
81
81
|
NPlusOneQuery.call_association(@post, :association)
|
82
82
|
end
|
83
83
|
|
@@ -149,7 +149,11 @@ module Bullet
|
|
149
149
|
|
150
150
|
expect(NPlusOneQuery).to receive(:caller_locations).and_return([in_project, *included_gems, excluded_gem])
|
151
151
|
expect(NPlusOneQuery).to receive(:conditions_met?).with(@post, :association).and_return(true)
|
152
|
-
expect(NPlusOneQuery).to receive(:create_notification).with(
|
152
|
+
expect(NPlusOneQuery).to receive(:create_notification).with(
|
153
|
+
[in_project, *included_gems],
|
154
|
+
'Post',
|
155
|
+
:association
|
156
|
+
)
|
153
157
|
NPlusOneQuery.call_association(@post, :association)
|
154
158
|
end
|
155
159
|
end
|
@@ -19,7 +19,9 @@ module Bullet
|
|
19
19
|
it 'should get call associations if object and association are both in eager_loadings and call_object_associations' do
|
20
20
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
21
21
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
22
|
-
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to eq(
|
22
|
+
expect(UnusedEagerLoading.send(:call_associations, @post.bullet_key, Set.new([:association]))).to eq(
|
23
|
+
[:association]
|
24
|
+
)
|
23
25
|
end
|
24
26
|
|
25
27
|
it 'should not get call associations if not exist in call_object_associations' do
|
@@ -30,18 +32,22 @@ module Bullet
|
|
30
32
|
|
31
33
|
context '.diff_object_associations' do
|
32
34
|
it 'should return associations not exist in call_association' do
|
33
|
-
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to eq(
|
35
|
+
expect(UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))).to eq(
|
36
|
+
[:association]
|
37
|
+
)
|
34
38
|
end
|
35
39
|
|
36
40
|
it 'should return empty if associations exist in call_association' do
|
37
41
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
38
42
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
39
|
-
expect(
|
43
|
+
expect(
|
44
|
+
UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))
|
45
|
+
).to be_empty
|
40
46
|
end
|
41
47
|
end
|
42
48
|
|
43
49
|
context '.check_unused_preload_associations' do
|
44
|
-
let(:paths) { [
|
50
|
+
let(:paths) { %w[/dir1 /dir1/subdir] }
|
45
51
|
it 'should create notification if object_association_diff is not empty' do
|
46
52
|
UnusedEagerLoading.add_object_associations(@post, :association)
|
47
53
|
allow(UnusedEagerLoading).to receive(:caller_in_project).and_return(paths)
|
@@ -53,7 +59,9 @@ module Bullet
|
|
53
59
|
UnusedEagerLoading.add_object_associations(@post, :association)
|
54
60
|
UnusedEagerLoading.add_eager_loadings([@post], :association)
|
55
61
|
UnusedEagerLoading.add_call_object_associations(@post, :association)
|
56
|
-
expect(
|
62
|
+
expect(
|
63
|
+
UnusedEagerLoading.send(:diff_object_associations, @post.bullet_key, Set.new([:association]))
|
64
|
+
).to be_empty
|
57
65
|
expect(UnusedEagerLoading).not_to receive(:create_notification).with('Post', [:association])
|
58
66
|
UnusedEagerLoading.check_unused_preload_associations
|
59
67
|
end
|
@@ -62,14 +70,23 @@ module Bullet
|
|
62
70
|
context '.add_eager_loadings' do
|
63
71
|
it 'should add objects, associations pair when eager_loadings are empty' do
|
64
72
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :associations)
|
65
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
|
73
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
|
74
|
+
[@post.bullet_key, @post2.bullet_key],
|
75
|
+
:associations
|
76
|
+
)
|
66
77
|
end
|
67
78
|
|
68
79
|
it 'should add objects, associations pair for existing eager_loadings' do
|
69
80
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association1)
|
70
81
|
UnusedEagerLoading.add_eager_loadings([@post, @post2], :association2)
|
71
|
-
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
|
72
|
-
|
82
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
|
83
|
+
[@post.bullet_key, @post2.bullet_key],
|
84
|
+
:association1
|
85
|
+
)
|
86
|
+
expect(UnusedEagerLoading.send(:eager_loadings)).to be_include(
|
87
|
+
[@post.bullet_key, @post2.bullet_key],
|
88
|
+
:association2
|
89
|
+
)
|
73
90
|
end
|
74
91
|
|
75
92
|
it 'should merge objects, associations pair for existing eager_loadings' do
|
@@ -10,30 +10,35 @@ describe Object do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
if mongoid?
|
13
|
-
it 'should return class with
|
13
|
+
it 'should return class with namespace and id composition' do
|
14
14
|
post = Mongoid::Post.first
|
15
15
|
expect(post.bullet_key).to eq("Mongoid::Post:#{post.id}")
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
context '
|
20
|
+
context 'bullet_primary_key_value' do
|
21
21
|
it 'should return id' do
|
22
22
|
post = Post.first
|
23
|
-
expect(post.
|
23
|
+
expect(post.bullet_primary_key_value).to eq(post.id)
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'should return primary key value' do
|
27
27
|
post = Post.first
|
28
28
|
Post.primary_key = 'name'
|
29
|
-
expect(post.
|
29
|
+
expect(post.bullet_primary_key_value).to eq(post.name)
|
30
30
|
Post.primary_key = 'id'
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'should return value for multiple primary keys' do
|
34
34
|
post = Post.first
|
35
35
|
allow(Post).to receive(:primary_keys).and_return(%i[category_id writer_id])
|
36
|
-
expect(post.
|
36
|
+
expect(post.bullet_primary_key_value).to eq("#{post.category_id},#{post.writer_id}")
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'it should return nil for unpersisted records' do
|
40
|
+
post = Post.new(id: 123)
|
41
|
+
expect(post.bullet_primary_key_value).to be_nil
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|
@@ -26,9 +26,7 @@ module Bullet
|
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'should leverage ENV parameter' do
|
29
|
-
temp_env_variable('USER', 'bogus')
|
30
|
-
expect(subject.whoami).to eq('user: bogus')
|
31
|
-
end
|
29
|
+
temp_env_variable('USER', 'bogus') { expect(subject.whoami).to eq('user: bogus') }
|
32
30
|
end
|
33
31
|
|
34
32
|
it 'should return blank if no user available' do
|
@@ -76,8 +74,8 @@ module Bullet
|
|
76
74
|
it 'should send full_notice to notifier' do
|
77
75
|
notifier = double
|
78
76
|
allow(subject).to receive(:notifier).and_return(notifier)
|
79
|
-
allow(subject).to receive(:notification_data).and_return(foo: :bar)
|
80
|
-
expect(notifier).to receive(:inline_notify).with(foo: :bar)
|
77
|
+
allow(subject).to receive(:notification_data).and_return({ foo: :bar })
|
78
|
+
expect(notifier).to receive(:inline_notify).with({ foo: :bar })
|
81
79
|
subject.notify_inline
|
82
80
|
end
|
83
81
|
end
|
@@ -86,8 +84,8 @@ module Bullet
|
|
86
84
|
it 'should send full_out_of_channel to notifier' do
|
87
85
|
notifier = double
|
88
86
|
allow(subject).to receive(:notifier).and_return(notifier)
|
89
|
-
allow(subject).to receive(:notification_data).and_return(foo: :bar)
|
90
|
-
expect(notifier).to receive(:out_of_channel_notify).with(foo: :bar)
|
87
|
+
allow(subject).to receive(:notification_data).and_return({ foo: :bar })
|
88
|
+
expect(notifier).to receive(:out_of_channel_notify).with({ foo: :bar })
|
91
89
|
subject.notify_out_of_channel
|
92
90
|
end
|
93
91
|
end
|
@@ -7,9 +7,22 @@ module Bullet
|
|
7
7
|
describe NPlusOneQuery do
|
8
8
|
subject { NPlusOneQuery.new([%w[caller1 caller2]], Post, %i[comments votes], 'path') }
|
9
9
|
|
10
|
-
it
|
11
|
-
|
12
|
-
|
10
|
+
it do
|
11
|
+
expect(subject.body_with_caller).to eq(
|
12
|
+
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n"
|
13
|
+
)
|
14
|
+
end
|
15
|
+
it do
|
16
|
+
expect([subject.body_with_caller, subject.body_with_caller]).to eq(
|
17
|
+
[
|
18
|
+
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n",
|
19
|
+
" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])\nCall stack\n caller1\n caller2\n"
|
20
|
+
]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
it do
|
24
|
+
expect(subject.body).to eq(" Post => [:comments, :votes]\n Add to your query: .includes([:comments, :votes])")
|
25
|
+
end
|
13
26
|
it { expect(subject.title).to eq('USE eager loading in path') }
|
14
27
|
end
|
15
28
|
end
|
@@ -7,7 +7,11 @@ module Bullet
|
|
7
7
|
describe UnusedEagerLoading do
|
8
8
|
subject { UnusedEagerLoading.new([''], Post, %i[comments votes], 'path') }
|
9
9
|
|
10
|
-
it
|
10
|
+
it do
|
11
|
+
expect(subject.body).to eq(
|
12
|
+
" Post => [:comments, :votes]\n Remove from your query: .includes([:comments, :votes])"
|
13
|
+
)
|
14
|
+
end
|
11
15
|
it { expect(subject.title).to eq('AVOID eager loading in path') }
|
12
16
|
end
|
13
17
|
end
|