Class: Woods::Extractors::LibExtractor

Inherits:
Object
  • Object
show all
Includes:
SharedDependencyScanner, SharedUtilityMethods
Defined in:
lib/woods/extractors/lib_extractor.rb

Overview

LibExtractor handles extraction of Ruby files from lib/.

The lib/ directory contains application infrastructure that sits outside Rails’ app/ convention: custom middleware, client wrappers, utility classes, domain-specific libraries, and framework extensions. These are often heavily referenced but invisible to app/-only extractors.

Excludes:

  • lib/tasks/ — handled by RakeTaskExtractor

  • lib/generators/ — Rails generator scaffolding, not application code

Handles:

  • Plain Ruby classes (with or without inheritance)

  • Module-only files (standalone modules without a class)

  • Namespaced classes (e.g., lib/external/analytics.rb → External::Analytics)

  • Files with multiple class definitions

Examples:

extractor = LibExtractor.new
units = extractor.extract_all
analytics = units.find { |u| u.identifier == "External::Analytics" }
analytics.[:entry_points]  # => ["call"]
analytics.[:parent_class]  # => nil

Constant Summary collapse

LIB_DIRECTORY =

Root directory to scan

'lib'
EXCLUDED_SEGMENTS =

Subdirectories to exclude from extraction

%w[/tasks/ /generators/].freeze

Constants included from SharedDependencyScanner

SharedDependencyScanner::FORM_ACTION_HELPER, SharedDependencyScanner::ROUTE_HELPER_PATTERN

Instance Method Summary collapse

Methods included from SharedDependencyScanner

#extract_constantize_targets, #scan_common_dependencies, #scan_form_dependencies, #scan_job_dependencies, #scan_mailer_dependencies, #scan_model_dependencies, #scan_navigation_dependencies, #scan_service_dependencies

Methods included from SharedUtilityMethods

#app_source?, #condition_label, #count_loc, #detect_entry_points, #extract_action_filter_actions, #extract_callback_conditions, #extract_class_methods, #extract_class_name, #extract_custom_errors, #extract_initialize_params, #extract_namespace, #extract_parent_class, #extract_public_methods, #resolve_source_location, #skip_file?

Constructor Details

#initializeLibExtractor

Returns a new instance of LibExtractor.



42
43
44
# File 'lib/woods/extractors/lib_extractor.rb', line 42

def initialize
  @lib_dir = Rails.root.join(LIB_DIRECTORY)
end

Instance Method Details

#extract_allArray<ExtractedUnit>

Extract all lib units from lib/*/.rb (excluding tasks and generators).

Returns:



49
50
51
52
53
54
55
56
57
# File 'lib/woods/extractors/lib_extractor.rb', line 49

def extract_all
  return [] unless @lib_dir.directory?

  Dir[@lib_dir.join('**/*.rb')].filter_map do |file|
    next if excluded_path?(file)

    extract_lib_file(file)
  end
end

#extract_lib_file(file_path) ⇒ ExtractedUnit?

Extract a single lib file.

Returns nil if the file cannot be read or yields no extractable unit. Module-only files are extracted (unlike some other extractors) since lib/ commonly contains standalone utility modules.

Parameters:

  • file_path (String)

    Absolute path to the Ruby file

Returns:



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/woods/extractors/lib_extractor.rb', line 67

def extract_lib_file(file_path)
  source = File.read(file_path)

  class_name = infer_class_name(file_path, source)
  return nil unless class_name

  unit = ExtractedUnit.new(
    type: :lib,
    identifier: class_name,
    file_path: file_path
  )

  unit.namespace    = extract_namespace(class_name)
  unit.source_code  = annotate_source(source, class_name)
  unit.     = (source, class_name)
  unit.dependencies = extract_dependencies(source)

  unit
rescue StandardError => e
  Rails.logger.error("Failed to extract lib file #{file_path}: #{e.message}")
  nil
end