Module: ActionReporter::PluginDiscovery

Defined in:
lib/action_reporter/plugin_discovery.rb

Overview

Plugin discovery mechanism for auto-discovering reporters This is lazy-loaded to avoid blocking application boot

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.discovered_reportersObject

Returns the value of attribute discovered_reporters.



18
19
20
# File 'lib/action_reporter/plugin_discovery.rb', line 18

def discovered_reporters
  @discovered_reporters
end

Class Method Details

.available_reportersArray<Class>

Get all available reporters (discovered + registered)

Returns:

  • (Array<Class>)

    Array of reporter classes



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/action_reporter/plugin_discovery.rb', line 67

def available_reporters
  reporters = discover.dup

  # Add registered reporters (lazy-loaded)
  registered_configs = discovery_lock.synchronize { registered_reporters.values.dup }
  registered_configs.each do |config|
    reporter_class = load_registered_reporter(config)
    reporters << reporter_class if reporter_class
  rescue => e
    # Silently skip registered reporters that can't be loaded (non-blocking)
    warn "ActionReporter: Failed to load registered reporter #{config[:class_name]}: #{e.message}"
  end

  reporters.uniq.freeze
end

.discoverArray<Class>

Discover reporters from the filesystem (lazy-loaded, cached) Only discovers files matching *_reporter.rb pattern in action_reporter/ directory

Returns:

  • (Array<Class>)

    Array of reporter classes



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/action_reporter/plugin_discovery.rb', line 42

def discover
  return discovered_reporters if discovered_reporters

  discovery_lock.synchronize do
    return discovered_reporters if discovered_reporters

    self.discovered_reporters = []
    # __dir__ is lib/action_reporter/, so we're already in the right directory
    base_path = __dir__

    # Discover built-in reporters
    Dir.glob(File.join(base_path, "*_reporter.rb")).each do |file|
      reporter_class = discover_reporter_from_file(file)
      discovered_reporters << reporter_class if reporter_class
    rescue => e
      # Silently skip files that can't be loaded (non-blocking)
      warn "ActionReporter: Failed to discover reporter from #{file}: #{e.message}"
    end

    self.discovered_reporters = discovered_reporters.freeze
  end
end

.discovery_lockObject



22
23
24
# File 'lib/action_reporter/plugin_discovery.rb', line 22

def discovery_lock
  @discovery_lock ||= Mutex.new
end

.register(name, class_name:, require_path:) ⇒ Object

Register a reporter manually (useful for custom reporters)

Parameters:

  • name (Symbol)

    Reporter name

  • class_name (String)

    Fully qualified class name

  • require_path (String)

    Path to require (e.g., "action_reporter/custom_reporter")



30
31
32
33
34
35
36
37
# File 'lib/action_reporter/plugin_discovery.rb', line 30

def register(name, class_name:, require_path:)
  discovery_lock.synchronize do
    registered_reporters[name] = {
      class_name: class_name,
      require_path: require_path
    }
  end
end

.registered_reportersObject

Accessors for class instance variables



14
15
16
# File 'lib/action_reporter/plugin_discovery.rb', line 14

def registered_reporters
  @registered_reporters ||= {}
end

.reset!Object

Reset discovery cache (useful for testing)



84
85
86
87
88
# File 'lib/action_reporter/plugin_discovery.rb', line 84

def reset!
  discovery_lock.synchronize do
    self.discovered_reporters = nil
  end
end