Skip to content

Commit 4cc0e70

Browse files
committed
feat: Autoload hook handlers
This makes it easier for the user to specify custom handlers. For example, specifying - methods: - Acme::Request.make handler_class: Acme::Request::AppmapHandler in the config file will make AppMap automatically require `acme/request/appmap_handler` before setting up the hook.
1 parent 72c4023 commit 4cc0e70

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

lib/appmap/config.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
require 'set'
55
require 'yaml'
66
require 'appmap/util'
7-
require 'appmap/handler/net_http'
8-
require 'appmap/handler/rails/template'
7+
require 'appmap/handler'
98
require 'appmap/service/guesser'
109
require 'appmap/swagger/configuration'
1110
require 'appmap/depends/configuration'
@@ -206,7 +205,7 @@ def declare_hook(hook_decl)
206205
}.compact
207206

208207
handler_class = hook_decl['handler_class']
209-
options[:handler_class] = Object.const_get(handler_class) if handler_class
208+
options[:handler_class] = Handler.find(handler_class) if handler_class
210209

211210
package_hooks(methods, **options)
212211
end

lib/appmap/handler.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# frozen_string_literal: true
2+
3+
require 'active_support/inflector/methods'
4+
5+
module AppMap
6+
# Specific hook handler classes and general related utilities.
7+
module Handler
8+
# Try to find handler module with a given name.
9+
#
10+
# If the module is not loaded, tries to require the appropriate file
11+
# using the usual conventions, eg. `Acme::Handler::AppMap` will try
12+
# to require `acme/handler/app_map`, then `acme/handler` and
13+
# finally `acme`. Raises NameError if the module could not be loaded
14+
# this way.
15+
def self.find(name)
16+
begin
17+
return Object.const_get name
18+
rescue NameError
19+
try_load ActiveSupport::Inflector.underscore name
20+
end
21+
Object.const_get name
22+
end
23+
24+
def self.try_load(fname)
25+
fname = fname.sub %r{^app_map/}, 'appmap/'
26+
fname = fname.split '/'
27+
until fname.empty?
28+
begin
29+
require fname.join '/'
30+
return
31+
rescue LoadError
32+
# pass
33+
end
34+
fname.pop
35+
end
36+
end
37+
end
38+
end

0 commit comments

Comments
 (0)