hyper-pure-sys 0.0.1

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/bullet-8.1.3/CHANGELOG.md +374 -0
  3. data/bullet-8.1.3/MIT-LICENSE +20 -0
  4. data/bullet-8.1.3/README.md +525 -0
  5. data/bullet-8.1.3/lib/bullet/active_job.rb +13 -0
  6. data/bullet-8.1.3/lib/bullet/active_record4.rb +197 -0
  7. data/bullet-8.1.3/lib/bullet/active_record41.rb +191 -0
  8. data/bullet-8.1.3/lib/bullet/active_record42.rb +262 -0
  9. data/bullet-8.1.3/lib/bullet/active_record5.rb +294 -0
  10. data/bullet-8.1.3/lib/bullet/active_record52.rb +278 -0
  11. data/bullet-8.1.3/lib/bullet/active_record60.rb +310 -0
  12. data/bullet-8.1.3/lib/bullet/active_record61.rb +310 -0
  13. data/bullet-8.1.3/lib/bullet/active_record70.rb +319 -0
  14. data/bullet-8.1.3/lib/bullet/active_record71.rb +319 -0
  15. data/bullet-8.1.3/lib/bullet/active_record72.rb +319 -0
  16. data/bullet-8.1.3/lib/bullet/active_record80.rb +319 -0
  17. data/bullet-8.1.3/lib/bullet/active_record81.rb +321 -0
  18. data/bullet-8.1.3/lib/bullet/bullet_xhr.js +64 -0
  19. data/bullet-8.1.3/lib/bullet/dependency.rb +165 -0
  20. data/bullet-8.1.3/lib/bullet/detector/association.rb +92 -0
  21. data/bullet-8.1.3/lib/bullet/detector/base.rb +8 -0
  22. data/bullet-8.1.3/lib/bullet/detector/counter_cache.rb +69 -0
  23. data/bullet-8.1.3/lib/bullet/detector/n_plus_one_query.rb +148 -0
  24. data/bullet-8.1.3/lib/bullet/detector/unused_eager_loading.rb +100 -0
  25. data/bullet-8.1.3/lib/bullet/detector.rb +11 -0
  26. data/bullet-8.1.3/lib/bullet/ext/object.rb +37 -0
  27. data/bullet-8.1.3/lib/bullet/ext/string.rb +14 -0
  28. data/bullet-8.1.3/lib/bullet/mongoid4x.rb +59 -0
  29. data/bullet-8.1.3/lib/bullet/mongoid5x.rb +59 -0
  30. data/bullet-8.1.3/lib/bullet/mongoid6x.rb +59 -0
  31. data/bullet-8.1.3/lib/bullet/mongoid7x.rb +74 -0
  32. data/bullet-8.1.3/lib/bullet/mongoid8x.rb +61 -0
  33. data/bullet-8.1.3/lib/bullet/mongoid9x.rb +74 -0
  34. data/bullet-8.1.3/lib/bullet/notification/base.rb +92 -0
  35. data/bullet-8.1.3/lib/bullet/notification/counter_cache.rb +15 -0
  36. data/bullet-8.1.3/lib/bullet/notification/n_plus_one_query.rb +31 -0
  37. data/bullet-8.1.3/lib/bullet/notification/unused_eager_loading.rb +31 -0
  38. data/bullet-8.1.3/lib/bullet/notification.rb +13 -0
  39. data/bullet-8.1.3/lib/bullet/notification_collector.rb +25 -0
  40. data/bullet-8.1.3/lib/bullet/rack.rb +186 -0
  41. data/bullet-8.1.3/lib/bullet/registry/association.rb +16 -0
  42. data/bullet-8.1.3/lib/bullet/registry/base.rb +46 -0
  43. data/bullet-8.1.3/lib/bullet/registry/call_stack.rb +17 -0
  44. data/bullet-8.1.3/lib/bullet/registry/object.rb +18 -0
  45. data/bullet-8.1.3/lib/bullet/registry.rb +10 -0
  46. data/bullet-8.1.3/lib/bullet/stack_trace_filter.rb +67 -0
  47. data/bullet-8.1.3/lib/bullet/version.rb +5 -0
  48. data/bullet-8.1.3/lib/bullet.rb +289 -0
  49. data/bullet-8.1.3/lib/generators/bullet/install_generator.rb +47 -0
  50. data/bullet-8.1.3/tasks/bullet_tasks.rake +11 -0
  51. data/hyper-pure-sys.gemspec +12 -0
  52. metadata +91 -0
@@ -0,0 +1,61 @@
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
+ private
50
+
51
+ def get_relation(name, association, object, reload = false)
52
+ result = origin_get_relation(name, association, object, reload)
53
+ unless association.embedded?
54
+ Bullet::Detector::NPlusOneQuery.call_association(self, name)
55
+ end
56
+ result
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Mongoid
5
+ def self.enable
6
+ require 'mongoid'
7
+ require 'rubygems'
8
+ ::Mongoid::Contextual::Mongo.class_eval do
9
+ alias_method :origin_first, :first
10
+ alias_method :origin_last, :last
11
+ alias_method :origin_each, :each
12
+ alias_method :origin_eager_load, :eager_load
13
+
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
21
+ end
22
+
23
+ def each(&_block)
24
+ return to_enum unless block_given?
25
+
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
43
+ end
44
+
45
+ if document_count == 1
46
+ Bullet::Detector::NPlusOneQuery.add_impossible_object(first_document)
47
+ yield(first_document)
48
+ end
49
+
50
+ self
51
+ end
52
+
53
+ def eager_load(docs)
54
+ associations = criteria.inclusions.map(&:name)
55
+ docs.each { |doc| Bullet::Detector::NPlusOneQuery.add_object_associations(doc, associations) }
56
+ Bullet::Detector::UnusedEagerLoading.add_eager_loadings(docs, associations)
57
+ origin_eager_load(docs)
58
+ end
59
+ end
60
+
61
+ ::Mongoid::Association::Accessors.class_eval do
62
+ alias_method :origin_get_relation, :get_relation
63
+
64
+ private
65
+
66
+ def get_relation(name, association, object, reload = false)
67
+ result = origin_get_relation(name, association, object, reload)
68
+ Bullet::Detector::NPlusOneQuery.call_association(self, name) unless association.embedded?
69
+ result
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Notification
5
+ class Base
6
+ attr_accessor :notifier, :url
7
+ attr_reader :base_class, :associations, :path
8
+
9
+ def initialize(base_class, association_or_associations, path = nil)
10
+ @base_class = base_class
11
+ @associations =
12
+ association_or_associations.is_a?(Array) ? association_or_associations : [association_or_associations]
13
+ @path = path
14
+ end
15
+
16
+ def title
17
+ raise NoMethodError, 'no method title defined'
18
+ end
19
+
20
+ def body
21
+ raise NoMethodError, 'no method body defined'
22
+ end
23
+
24
+ def call_stack_messages
25
+ ''
26
+ end
27
+
28
+ def whoami
29
+ @user ||=
30
+ ENV['USER'].presence ||
31
+ (
32
+ begin
33
+ `whoami`.chomp
34
+ rescue StandardError
35
+ ''
36
+ end
37
+ )
38
+ @user.present? ? "user: #{@user}" : ''
39
+ end
40
+
41
+ def body_with_caller
42
+ "#{body}\n#{call_stack_messages}\n"
43
+ end
44
+
45
+ def notify_inline
46
+ notifier.inline_notify(notification_data)
47
+ end
48
+
49
+ def notify_out_of_channel
50
+ notifier.out_of_channel_notify(notification_data)
51
+ end
52
+
53
+ def short_notice
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(' ')
61
+ end
62
+
63
+ def notification_data
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
70
+ end
71
+
72
+ def eql?(other)
73
+ self.class == other.class && klazz_associations_str == other.klazz_associations_str
74
+ end
75
+
76
+ def hash
77
+ [self.class, klazz_associations_str].hash
78
+ end
79
+
80
+ protected
81
+
82
+ def klazz_associations_str
83
+ " #{@base_class} => [#{@associations.map(&:inspect).join(', ')}]"
84
+ end
85
+
86
+ def associations_str
87
+ ".includes(#{@associations.map { |a| a.to_s.to_sym }
88
+ .inspect})"
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Notification
5
+ class CounterCache < Base
6
+ def body
7
+ klazz_associations_str
8
+ end
9
+
10
+ def title
11
+ 'Need Counter Cache with Active Record size'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Notification
5
+ class NPlusOneQuery < Base
6
+ def initialize(callers, base_class, associations, path = nil)
7
+ super(base_class, associations, path)
8
+
9
+ @callers = callers
10
+ end
11
+
12
+ def body
13
+ "#{klazz_associations_str}\n Add to your query: #{associations_str}"
14
+ end
15
+
16
+ def title
17
+ "USE eager loading #{@path ? "in #{@path}" : 'detected'}"
18
+ end
19
+
20
+ def notification_data
21
+ super.merge(backtrace: [])
22
+ end
23
+
24
+ protected
25
+
26
+ def call_stack_messages
27
+ (['Call stack'] + @callers).join("\n ")
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Notification
5
+ class UnusedEagerLoading < Base
6
+ def initialize(callers, base_class, associations, path = nil)
7
+ super(base_class, associations, path)
8
+
9
+ @callers = callers
10
+ end
11
+
12
+ def body
13
+ "#{klazz_associations_str}\n Remove from your query: #{associations_str}"
14
+ end
15
+
16
+ def title
17
+ "AVOID eager loading #{@path ? "in #{@path}" : 'detected'}"
18
+ end
19
+
20
+ def notification_data
21
+ super.merge(backtrace: [])
22
+ end
23
+
24
+ protected
25
+
26
+ def call_stack_messages
27
+ (['Call stack'] + @callers).join("\n ")
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Notification
5
+ autoload :Base, 'bullet/notification/base'
6
+ autoload :UnusedEagerLoading, 'bullet/notification/unused_eager_loading'
7
+ autoload :NPlusOneQuery, 'bullet/notification/n_plus_one_query'
8
+ autoload :CounterCache, 'bullet/notification/counter_cache'
9
+
10
+ class UnoptimizedQueryError < StandardError
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module Bullet
6
+ class NotificationCollector
7
+ attr_reader :collection
8
+
9
+ def initialize
10
+ reset
11
+ end
12
+
13
+ def reset
14
+ @collection = Set.new
15
+ end
16
+
17
+ def add(value)
18
+ @collection << value
19
+ end
20
+
21
+ def notifications_present?
22
+ !@collection.empty?
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/request'
4
+ require 'json'
5
+ require 'cgi'
6
+
7
+ module Bullet
8
+ class Rack
9
+ include Dependency
10
+
11
+ NONCE_MATCHER = /(script|style)-src .*'nonce-(?<nonce>[A-Za-z0-9+\/]+={0,2})'/
12
+
13
+ def initialize(app)
14
+ @app = app
15
+ end
16
+
17
+ def call(env)
18
+ return @app.call(env) unless Bullet.enable?
19
+
20
+ Bullet.start_request
21
+ status, headers, response = @app.call(env)
22
+
23
+ response_body = nil
24
+
25
+ if Bullet.notification? || Bullet.always_append_html_body
26
+ request = ::Rack::Request.new(env)
27
+ if Bullet.inject_into_page? && !skip_html_injection?(request) && !file?(headers) && !sse?(headers) && !empty?(response) && status == 200
28
+ if html_request?(headers, response)
29
+ response_body = response_body(response)
30
+
31
+ with_security_policy_nonce(headers) do |nonce|
32
+ response_body = append_to_html_body(response_body, footer_note(nonce)) if Bullet.add_footer
33
+ response_body = append_to_html_body(response_body, Bullet.gather_inline_notifications)
34
+ if Bullet.add_footer && !Bullet.skip_http_headers
35
+ response_body = append_to_html_body(response_body, xhr_script(nonce))
36
+ end
37
+ end
38
+
39
+ headers['Content-Length'] = response_body.bytesize.to_s
40
+ elsif !Bullet.skip_http_headers
41
+ set_header(headers, 'X-bullet-footer-text', Bullet.footer_info.uniq) if Bullet.add_footer
42
+ set_header(headers, 'X-bullet-console-text', Bullet.text_notifications) if Bullet.console_enabled?
43
+ end
44
+ end
45
+ Bullet.perform_out_of_channel_notifications(env)
46
+ end
47
+ [status, headers, response_body ? [response_body] : response]
48
+ ensure
49
+ Bullet.end_request
50
+ end
51
+
52
+ # fix issue if response's body is a Proc
53
+ def empty?(response)
54
+ # response may be ["Not Found"], ["Move Permanently"], etc, but
55
+ # those should not happen if the status is 200
56
+ return true if !response.respond_to?(:body) && !response.respond_to?(:first)
57
+
58
+ body = response_body(response)
59
+ body.nil? || body.empty?
60
+ end
61
+
62
+ def append_to_html_body(response_body, content)
63
+ body = response_body.dup
64
+ content = content.html_safe if content.respond_to?(:html_safe)
65
+ if body.include?('</body>')
66
+ position = body.rindex('</body>')
67
+ body.insert(position, content)
68
+ else
69
+ body << content
70
+ end
71
+ end
72
+
73
+ def footer_note(nonce = nil)
74
+ %(<details id="bullet-footer" data-is-bullet-footer><summary>Bullet Warnings</summary><div>#{Bullet.footer_info.uniq.join('<br>')}#{footer_console_message(nonce)}</div>#{footer_style(nonce)}</details>)
75
+ end
76
+
77
+ # Make footer styles work with ContentSecurityPolicy style-src as self
78
+ def footer_style(nonce = nil)
79
+ css = <<~CSS
80
+ details#bullet-footer {cursor: pointer; position: fixed; left: 0px; bottom: 0px; z-index: 9999; background: #fdf2f2; color: #9b1c1c; font-size: 12px; border-radius: 0px 8px 0px 0px; border: 1px solid #9b1c1c;}
81
+ details#bullet-footer summary {font-weight: 600; padding: 2px 8px;}
82
+ details#bullet-footer div {padding: 8px; border-top: 1px solid #9b1c1c;}
83
+ CSS
84
+ if nonce
85
+ %(<style type="text/css" nonce="#{nonce}">#{css}</style>)
86
+ else
87
+ %(<style type="text/css">#{css}</style>)
88
+ end
89
+ end
90
+
91
+ def set_header(headers, header_name, header_array)
92
+ # Many proxy applications such as Nginx and AWS ELB limit
93
+ # the size a header to 8KB, so truncate the list of reports to
94
+ # be under that limit
95
+ header_array.pop while JSON.generate(header_array).length > 8 * 1024
96
+ headers[header_name] = JSON.generate(header_array)
97
+ end
98
+
99
+ def skip_html_injection?(request)
100
+ query_string = request.env['QUERY_STRING']
101
+ return false if query_string.nil? || query_string.empty?
102
+
103
+ params = simple_parse_query_string(query_string)
104
+ params['skip_html_injection'] == 'true'
105
+ end
106
+
107
+ # Simple query string parser
108
+ def simple_parse_query_string(query_string)
109
+ params = {}
110
+ query_string.split('&').each do |pair|
111
+ key, value = pair.split('=', 2).map { |s| CGI.unescape(s) }
112
+ params[key] = value if key && !key.empty?
113
+ end
114
+ params
115
+ end
116
+
117
+ def file?(headers)
118
+ headers['Content-Transfer-Encoding'] == 'binary' || headers['Content-Disposition']
119
+ end
120
+
121
+ def sse?(headers)
122
+ headers['Content-Type'] == 'text/event-stream'
123
+ end
124
+
125
+ def html_request?(headers, response)
126
+ headers['Content-Type']&.include?('text/html')
127
+ end
128
+
129
+ def response_body(response)
130
+ if response.respond_to?(:body)
131
+ Array === response.body ? response.body.first : response.body
132
+ elsif response.respond_to?(:first)
133
+ response.first
134
+ end
135
+ end
136
+
137
+ private
138
+
139
+ def footer_console_message(nonce = nil)
140
+ if Bullet.console_enabled?
141
+ footer = %(<br/><span id="console-message">See 'Uniform Notifier' in JS Console for Stacktrace</span>)
142
+ css = "details#bullet-footer #console-message {font-style: italic;}"
143
+ style =
144
+ if nonce
145
+ %(<style type="text/css" nonce="#{nonce}">#{css}</style>)
146
+ else
147
+ %(<style type="text/css">#{css}</style>)
148
+ end
149
+
150
+ footer + style
151
+ end
152
+ end
153
+
154
+ # Make footer work for XHR requests by appending data to the footer
155
+ def xhr_script(nonce = nil)
156
+ script = File.read("#{__dir__}/bullet_xhr.js")
157
+
158
+ if nonce
159
+ "<script type='text/javascript' nonce='#{nonce}'>#{script}</script>"
160
+ else
161
+ "<script type='text/javascript'>#{script}</script>"
162
+ end
163
+ end
164
+
165
+ def with_security_policy_nonce(headers)
166
+ csp = headers['Content-Security-Policy'] || headers['Content-Security-Policy-Report-Only'] || ''
167
+ matched = csp.match(NONCE_MATCHER)
168
+ nonce = matched[:nonce] if matched
169
+
170
+ if nonce
171
+ console_enabled = UniformNotifier.console
172
+ alert_enabled = UniformNotifier.alert
173
+
174
+ UniformNotifier.console = { attributes: { nonce: nonce } } if console_enabled
175
+ UniformNotifier.alert = { attributes: { nonce: nonce } } if alert_enabled
176
+
177
+ yield nonce
178
+
179
+ UniformNotifier.console = console_enabled
180
+ UniformNotifier.alert = alert_enabled
181
+ else
182
+ yield
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Registry
5
+ class Association < Base
6
+ def merge(base, associations)
7
+ @registry.merge!(base => associations)
8
+ end
9
+
10
+ def similarly_associated(base, associations)
11
+ @registry.select { |key, value| key.include?(base) && value == associations }
12
+ .collect(&:first).flatten
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Registry
5
+ class Base
6
+ attr_reader :registry
7
+
8
+ def initialize
9
+ @registry = {}
10
+ end
11
+
12
+ def [](key)
13
+ @registry[key]
14
+ end
15
+
16
+ def each(&block)
17
+ @registry.each(&block)
18
+ end
19
+
20
+ def delete(base)
21
+ @registry.delete(base)
22
+ end
23
+
24
+ def select(*args, &block)
25
+ @registry.select(*args, &block)
26
+ end
27
+
28
+ def add(key, value)
29
+ @registry[key] ||= Set.new
30
+ if value.is_a? Array
31
+ @registry[key] += value
32
+ else
33
+ @registry[key] << value
34
+ end
35
+ end
36
+
37
+ def include?(key, value)
38
+ key?(key) && @registry[key].include?(value)
39
+ end
40
+
41
+ def key?(key)
42
+ @registry.key?(key)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Registry
5
+ class CallStack < Base
6
+ # remembers found association backtrace
7
+ # if backtrace is provided, it will be used and override any existing value
8
+ def add(key, backtrace = nil)
9
+ if backtrace
10
+ @registry[key] = backtrace
11
+ else
12
+ @registry[key] ||= Thread.current.backtrace
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ using Bullet::Ext::Object
4
+ using Bullet::Ext::String
5
+
6
+ module Bullet
7
+ module Registry
8
+ class Object < Base
9
+ def add(bullet_key)
10
+ super(bullet_key.bullet_class_name, bullet_key)
11
+ end
12
+
13
+ def include?(bullet_key)
14
+ super(bullet_key.bullet_class_name, bullet_key)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bullet
4
+ module Registry
5
+ autoload :Base, 'bullet/registry/base'
6
+ autoload :Object, 'bullet/registry/object'
7
+ autoload :Association, 'bullet/registry/association'
8
+ autoload :CallStack, 'bullet/registry/call_stack'
9
+ end
10
+ end