bullet 8.0.8 → 8.1.0.beta1
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 +5 -0
- data/README.md +6 -2
- data/lib/bullet/active_record81.rb +319 -0
- data/lib/bullet/dependency.rb +6 -0
- data/lib/bullet/mongoid4x.rb +2 -0
- data/lib/bullet/mongoid5x.rb +2 -0
- data/lib/bullet/mongoid6x.rb +2 -0
- data/lib/bullet/mongoid7x.rb +2 -0
- data/lib/bullet/mongoid8x.rb +2 -0
- data/lib/bullet/mongoid9x.rb +2 -0
- data/lib/bullet/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2574a64c0e7be33a0d8ba57e0c23555e70b09999ae9d6d2d8ce0abf30222c782
|
4
|
+
data.tar.gz: 1da3e33d8752367ff389f41f16eff4e7f314084954160a21cc5aac8f1f3b0fca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b324a99664cfbc4892cee40c2c80f32a46b313c0ea155de6eb36c4809d372e90c8ed5c3eaf20d90de39fbfe03ce1251d128c56f6a30343a2fa25b9d152cff6d
|
7
|
+
data.tar.gz: 8be2ed0c9d8ce3e9868c554919f9d5e08b04f16876b1f7999470c05a47ffae82f5c896fd38f39518aef3f8f952b44ffe072f3363bd7e7a24b33bdb53cf51e809
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -71,10 +71,14 @@ config.after_initialize do
|
|
71
71
|
Bullet.rollbar = true
|
72
72
|
Bullet.add_footer = true
|
73
73
|
Bullet.skip_html_injection = false
|
74
|
+
Bullet.skip_http_headers = false
|
74
75
|
Bullet.stacktrace_includes = [ 'your_gem', 'your_middleware' ]
|
75
76
|
Bullet.stacktrace_excludes = [ 'their_gem', 'their_middleware', ['my_file.rb', 'my_method'], ['my_file.rb', 16..20] ]
|
76
77
|
Bullet.slack = { webhook_url: 'http://some.slack.url', channel: '#default', username: 'notifier' }
|
77
78
|
Bullet.opentelemetry = true
|
79
|
+
Bullet.raise = false
|
80
|
+
Bullet.always_append_html_body = false
|
81
|
+
Bullet.skip_user_in_notification = false
|
78
82
|
end
|
79
83
|
```
|
80
84
|
|
@@ -82,6 +86,7 @@ The notifier of Bullet is a wrap of [uniform_notifier](https://github.com/flyerh
|
|
82
86
|
|
83
87
|
The code above will enable all of the Bullet notification systems:
|
84
88
|
* `Bullet.enable`: enable Bullet gem, otherwise do nothing
|
89
|
+
* `Bullet.sentry`: add notifications to sentry
|
85
90
|
* `Bullet.alert`: pop up a JavaScript alert in the browser
|
86
91
|
* `Bullet.bullet_logger`: log to the Bullet log file (Rails.root/log/bullet.log)
|
87
92
|
* `Bullet.console`: log warnings to your browser's console.log (Safari/Webkit browsers or Firefox w/Firebug installed)
|
@@ -89,10 +94,9 @@ The code above will enable all of the Bullet notification systems:
|
|
89
94
|
* `Bullet.rails_logger`: add warnings directly to the Rails log
|
90
95
|
* `Bullet.honeybadger`: add notifications to Honeybadger
|
91
96
|
* `Bullet.bugsnag`: add notifications to bugsnag
|
92
|
-
* `Bullet.airbrake`: add notifications to airbrake
|
93
97
|
* `Bullet.appsignal`: add notifications to AppSignal
|
98
|
+
* `Bullet.airbrake`: add notifications to airbrake
|
94
99
|
* `Bullet.rollbar`: add notifications to rollbar
|
95
|
-
* `Bullet.sentry`: add notifications to sentry
|
96
100
|
* `Bullet.add_footer`: adds the details in the bottom left corner of the page. Double click the footer or use close button to hide footer.
|
97
101
|
* `Bullet.skip_html_injection`: prevents Bullet from injecting code into the returned HTML. This must be false for receiving alerts, showing the footer or console logging.
|
98
102
|
* `Bullet.skip_http_headers`: don't add headers to API requests, and remove the javascript that relies on them. Note that this prevents bullet from logging warnings to the browser console or updating the footer.
|
@@ -0,0 +1,319 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bullet
|
4
|
+
module SaveWithBulletSupport
|
5
|
+
def _create_record(*)
|
6
|
+
super do
|
7
|
+
Bullet::Detector::NPlusOneQuery.update_inversed_object(self)
|
8
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(self)
|
9
|
+
yield(self) if block_given?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ActiveRecord
|
15
|
+
def self.enable
|
16
|
+
require 'active_record'
|
17
|
+
::ActiveRecord::Base.extend(
|
18
|
+
Module.new do
|
19
|
+
def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
|
20
|
+
result = super
|
21
|
+
if Bullet.start?
|
22
|
+
if result.is_a? Array
|
23
|
+
if result.size > 1
|
24
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
25
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
26
|
+
elsif result.size == 1
|
27
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
28
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
29
|
+
end
|
30
|
+
elsif result.is_a? ::ActiveRecord::Base
|
31
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result)
|
32
|
+
Bullet::Detector::CounterCache.add_impossible_object(result)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
end
|
38
|
+
)
|
39
|
+
|
40
|
+
::ActiveRecord::Base.prepend(SaveWithBulletSupport)
|
41
|
+
|
42
|
+
::ActiveRecord::Relation.prepend(
|
43
|
+
Module.new do
|
44
|
+
# if select a collection of objects, then these objects have possible to cause N+1 query.
|
45
|
+
# if select only one object, then the only one object has impossible to cause N+1 query.
|
46
|
+
def records
|
47
|
+
result = super
|
48
|
+
if Bullet.start?
|
49
|
+
if result.first.class.name !~ /^HABTM_/
|
50
|
+
if result.size > 1
|
51
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result)
|
52
|
+
Bullet::Detector::CounterCache.add_possible_objects(result)
|
53
|
+
elsif result.size == 1
|
54
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result.first)
|
55
|
+
Bullet::Detector::CounterCache.add_impossible_object(result.first)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
result
|
60
|
+
end
|
61
|
+
end
|
62
|
+
)
|
63
|
+
|
64
|
+
::ActiveRecord::Associations::Preloader::Batch.prepend(
|
65
|
+
Module.new do
|
66
|
+
def call
|
67
|
+
if Bullet.start?
|
68
|
+
@preloaders.each do |preloader|
|
69
|
+
preloader.records.each { |record|
|
70
|
+
Bullet::Detector::Association.add_object_associations(record, preloader.associations)
|
71
|
+
}
|
72
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(preloader.records, preloader.associations)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
super
|
76
|
+
end
|
77
|
+
end
|
78
|
+
)
|
79
|
+
|
80
|
+
::ActiveRecord::Associations::Preloader::Branch.prepend(
|
81
|
+
Module.new do
|
82
|
+
def preloaders_for_reflection(reflection, reflection_records)
|
83
|
+
if Bullet.start?
|
84
|
+
reflection_records.compact!
|
85
|
+
if reflection_records.first.class.name !~ /^HABTM_/
|
86
|
+
reflection_records.each { |record|
|
87
|
+
Bullet::Detector::Association.add_object_associations(record, reflection.name)
|
88
|
+
}
|
89
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(reflection_records, reflection.name)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
super
|
93
|
+
end
|
94
|
+
end
|
95
|
+
)
|
96
|
+
|
97
|
+
::ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(
|
98
|
+
Module.new do
|
99
|
+
def source_preloaders
|
100
|
+
if Bullet.start? && !defined?(@source_preloaders)
|
101
|
+
preloaders = super
|
102
|
+
preloaders.each do |preloader|
|
103
|
+
reflection_name = preloader.send(:reflection).name
|
104
|
+
preloader.send(:owners).each do |owner|
|
105
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection_name)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
else
|
109
|
+
super
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
)
|
114
|
+
|
115
|
+
::ActiveRecord::Associations::JoinDependency.prepend(
|
116
|
+
Module.new do
|
117
|
+
def instantiate(result_set, strict_loading_value, &block)
|
118
|
+
@bullet_eager_loadings = {}
|
119
|
+
records = super
|
120
|
+
|
121
|
+
if Bullet.start?
|
122
|
+
@bullet_eager_loadings.each do |_klazz, eager_loadings_hash|
|
123
|
+
objects = eager_loadings_hash.keys
|
124
|
+
Bullet::Detector::UnusedEagerLoading.add_eager_loadings(
|
125
|
+
objects,
|
126
|
+
eager_loadings_hash[objects.first].to_a
|
127
|
+
)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
records
|
131
|
+
end
|
132
|
+
|
133
|
+
def construct(ar_parent, parent, row, seen, model_cache, strict_loading_value)
|
134
|
+
if Bullet.start?
|
135
|
+
unless ar_parent.nil?
|
136
|
+
parent.children.each do |node|
|
137
|
+
key = aliases.column_alias(node, node.primary_key)
|
138
|
+
id = row[key]
|
139
|
+
next unless id.nil?
|
140
|
+
|
141
|
+
associations = [node.reflection.name]
|
142
|
+
if node.reflection.through_reflection?
|
143
|
+
associations << node.reflection.through_reflection.name
|
144
|
+
end
|
145
|
+
associations.each do |association|
|
146
|
+
Bullet::Detector::Association.add_object_associations(ar_parent, association)
|
147
|
+
Bullet::Detector::NPlusOneQuery.call_association(ar_parent, association)
|
148
|
+
@bullet_eager_loadings[ar_parent.class] ||= {}
|
149
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] ||= Set.new
|
150
|
+
@bullet_eager_loadings[ar_parent.class][ar_parent] << association
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
super
|
157
|
+
end
|
158
|
+
|
159
|
+
# call join associations
|
160
|
+
def construct_model(record, node, row, model_cache, id, strict_loading_value)
|
161
|
+
result = super
|
162
|
+
|
163
|
+
if Bullet.start?
|
164
|
+
associations = [node.reflection.name]
|
165
|
+
if node.reflection.through_reflection?
|
166
|
+
associations << node.reflection.through_reflection.name
|
167
|
+
end
|
168
|
+
associations.each do |association|
|
169
|
+
Bullet::Detector::Association.add_object_associations(record, association)
|
170
|
+
Bullet::Detector::NPlusOneQuery.call_association(record, association)
|
171
|
+
@bullet_eager_loadings[record.class] ||= {}
|
172
|
+
@bullet_eager_loadings[record.class][record] ||= Set.new
|
173
|
+
@bullet_eager_loadings[record.class][record] << association
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
result
|
178
|
+
end
|
179
|
+
end
|
180
|
+
)
|
181
|
+
|
182
|
+
::ActiveRecord::Associations::Association.prepend(
|
183
|
+
Module.new do
|
184
|
+
def inversed_from(record)
|
185
|
+
if Bullet.start?
|
186
|
+
Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
|
187
|
+
end
|
188
|
+
super
|
189
|
+
end
|
190
|
+
|
191
|
+
def inversed_from_queries(record)
|
192
|
+
if Bullet.start? && inversable?(record)
|
193
|
+
Bullet::Detector::NPlusOneQuery.add_inversed_object(owner, reflection.name)
|
194
|
+
end
|
195
|
+
super
|
196
|
+
end
|
197
|
+
end
|
198
|
+
)
|
199
|
+
|
200
|
+
::ActiveRecord::Associations::CollectionAssociation.prepend(
|
201
|
+
Module.new do
|
202
|
+
def load_target
|
203
|
+
records = super
|
204
|
+
|
205
|
+
if Bullet.start?
|
206
|
+
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
207
|
+
association = owner.association(reflection.through_reflection.name)
|
208
|
+
if association.loaded?
|
209
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
|
210
|
+
Array.wrap(association.target).each do |through_record|
|
211
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
212
|
+
end
|
213
|
+
|
214
|
+
if reflection.through_reflection != through_reflection
|
215
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
220
|
+
if records.first.class.name !~ /^HABTM_/
|
221
|
+
if records.size > 1
|
222
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(records)
|
223
|
+
Bullet::Detector::CounterCache.add_possible_objects(records)
|
224
|
+
elsif records.size == 1
|
225
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(records.first)
|
226
|
+
Bullet::Detector::CounterCache.add_impossible_object(records.first)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
records
|
231
|
+
end
|
232
|
+
|
233
|
+
def empty?
|
234
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
235
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
236
|
+
end
|
237
|
+
super
|
238
|
+
end
|
239
|
+
|
240
|
+
def include?(object)
|
241
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name) if Bullet.start?
|
242
|
+
super
|
243
|
+
end
|
244
|
+
end
|
245
|
+
)
|
246
|
+
|
247
|
+
::ActiveRecord::Associations::SingularAssociation.prepend(
|
248
|
+
Module.new do
|
249
|
+
# call has_one and belongs_to associations
|
250
|
+
def reader
|
251
|
+
result = super
|
252
|
+
|
253
|
+
if Bullet.start?
|
254
|
+
if owner.class.name !~ /^HABTM_/
|
255
|
+
if is_a? ::ActiveRecord::Associations::ThroughAssociation
|
256
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.through_reflection.name)
|
257
|
+
association = owner.association(reflection.through_reflection.name)
|
258
|
+
Array.wrap(association.target).each do |through_record|
|
259
|
+
Bullet::Detector::NPlusOneQuery.call_association(through_record, source_reflection.name)
|
260
|
+
end
|
261
|
+
|
262
|
+
if reflection.through_reflection != through_reflection
|
263
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, through_reflection.name)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
267
|
+
|
268
|
+
if Bullet::Detector::NPlusOneQuery.impossible?(owner)
|
269
|
+
Bullet::Detector::NPlusOneQuery.add_impossible_object(result) if result
|
270
|
+
else
|
271
|
+
Bullet::Detector::NPlusOneQuery.add_possible_objects(result) if result
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
result
|
276
|
+
end
|
277
|
+
end
|
278
|
+
)
|
279
|
+
|
280
|
+
::ActiveRecord::Associations::HasManyAssociation.prepend(
|
281
|
+
Module.new do
|
282
|
+
def empty?
|
283
|
+
result = super
|
284
|
+
if Bullet.start? && !reflection.has_cached_counter?
|
285
|
+
Bullet::Detector::NPlusOneQuery.call_association(owner, reflection.name)
|
286
|
+
end
|
287
|
+
result
|
288
|
+
end
|
289
|
+
|
290
|
+
def count_records
|
291
|
+
result = reflection.has_cached_counter?
|
292
|
+
if Bullet.start? && !result && !is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
293
|
+
Bullet::Detector::CounterCache.add_counter_cache(owner, reflection.name)
|
294
|
+
end
|
295
|
+
super
|
296
|
+
end
|
297
|
+
end
|
298
|
+
)
|
299
|
+
|
300
|
+
::ActiveRecord::Associations::CollectionProxy.prepend(
|
301
|
+
Module.new do
|
302
|
+
def count(column_name = nil)
|
303
|
+
if Bullet.start? && !proxy_association.is_a?(::ActiveRecord::Associations::ThroughAssociation)
|
304
|
+
Bullet::Detector::CounterCache.add_counter_cache(
|
305
|
+
proxy_association.owner,
|
306
|
+
proxy_association.reflection.name
|
307
|
+
)
|
308
|
+
Bullet::Detector::NPlusOneQuery.call_association(
|
309
|
+
proxy_association.owner,
|
310
|
+
proxy_association.reflection.name
|
311
|
+
)
|
312
|
+
end
|
313
|
+
super(column_name)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
data/lib/bullet/dependency.rb
CHANGED
@@ -37,6 +37,8 @@ module Bullet
|
|
37
37
|
'active_record72'
|
38
38
|
elsif active_record80?
|
39
39
|
'active_record80'
|
40
|
+
elsif active_record81?
|
41
|
+
'active_record81'
|
40
42
|
else
|
41
43
|
raise "Bullet does not support active_record #{::ActiveRecord::VERSION::STRING} yet"
|
42
44
|
end
|
@@ -132,6 +134,10 @@ module Bullet
|
|
132
134
|
active_record8? && ::ActiveRecord::VERSION::MINOR == 0
|
133
135
|
end
|
134
136
|
|
137
|
+
def active_record81?
|
138
|
+
active_record8? && ::ActiveRecord::VERSION::MINOR == 1
|
139
|
+
end
|
140
|
+
|
135
141
|
def mongoid4x?
|
136
142
|
mongoid? && ::Mongoid::VERSION =~ /\A4/
|
137
143
|
end
|
data/lib/bullet/mongoid4x.rb
CHANGED
@@ -46,6 +46,8 @@ module Bullet
|
|
46
46
|
::Mongoid::Relations::Accessors.class_eval do
|
47
47
|
alias_method :origin_get_relation, :get_relation
|
48
48
|
|
49
|
+
private
|
50
|
+
|
49
51
|
def get_relation(name, metadata, object, reload = false)
|
50
52
|
result = origin_get_relation(name, metadata, object, reload)
|
51
53
|
Bullet::Detector::NPlusOneQuery.call_association(self, name) if metadata.macro !~ /embed/
|
data/lib/bullet/mongoid5x.rb
CHANGED
@@ -46,6 +46,8 @@ module Bullet
|
|
46
46
|
::Mongoid::Relations::Accessors.class_eval do
|
47
47
|
alias_method :origin_get_relation, :get_relation
|
48
48
|
|
49
|
+
private
|
50
|
+
|
49
51
|
def get_relation(name, metadata, object, reload = false)
|
50
52
|
result = origin_get_relation(name, metadata, object, reload)
|
51
53
|
Bullet::Detector::NPlusOneQuery.call_association(self, name) if metadata.macro !~ /embed/
|
data/lib/bullet/mongoid6x.rb
CHANGED
@@ -46,6 +46,8 @@ module Bullet
|
|
46
46
|
::Mongoid::Relations::Accessors.class_eval do
|
47
47
|
alias_method :origin_get_relation, :get_relation
|
48
48
|
|
49
|
+
private
|
50
|
+
|
49
51
|
def get_relation(name, metadata, object, reload = false)
|
50
52
|
result = origin_get_relation(name, metadata, object, reload)
|
51
53
|
Bullet::Detector::NPlusOneQuery.call_association(self, name) if metadata.macro !~ /embed/
|
data/lib/bullet/mongoid7x.rb
CHANGED
@@ -61,6 +61,8 @@ module Bullet
|
|
61
61
|
::Mongoid::Association::Accessors.class_eval do
|
62
62
|
alias_method :origin_get_relation, :get_relation
|
63
63
|
|
64
|
+
private
|
65
|
+
|
64
66
|
def get_relation(name, association, object, reload = false)
|
65
67
|
result = origin_get_relation(name, association, object, reload)
|
66
68
|
Bullet::Detector::NPlusOneQuery.call_association(self, name) unless association.embedded?
|
data/lib/bullet/mongoid8x.rb
CHANGED
@@ -46,6 +46,8 @@ module Bullet
|
|
46
46
|
::Mongoid::Association::Accessors.class_eval do
|
47
47
|
alias_method :origin_get_relation, :get_relation
|
48
48
|
|
49
|
+
private
|
50
|
+
|
49
51
|
def get_relation(name, association, object, reload = false)
|
50
52
|
result = origin_get_relation(name, association, object, reload)
|
51
53
|
unless association.embedded?
|
data/lib/bullet/mongoid9x.rb
CHANGED
@@ -61,6 +61,8 @@ module Bullet
|
|
61
61
|
::Mongoid::Association::Accessors.class_eval do
|
62
62
|
alias_method :origin_get_relation, :get_relation
|
63
63
|
|
64
|
+
private
|
65
|
+
|
64
66
|
def get_relation(name, association, object, reload = false)
|
65
67
|
result = origin_get_relation(name, association, object, reload)
|
66
68
|
Bullet::Detector::NPlusOneQuery.call_association(self, name) unless association.embedded?
|
data/lib/bullet/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.0.
|
4
|
+
version: 8.1.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Huang
|
@@ -60,6 +60,7 @@ files:
|
|
60
60
|
- lib/bullet/active_record71.rb
|
61
61
|
- lib/bullet/active_record72.rb
|
62
62
|
- lib/bullet/active_record80.rb
|
63
|
+
- lib/bullet/active_record81.rb
|
63
64
|
- lib/bullet/bullet_xhr.js
|
64
65
|
- lib/bullet/dependency.rb
|
65
66
|
- lib/bullet/detector.rb
|