Module: Familia::Features::Autoloadable::ClassMethods

Defined in:
lib/familia/features/autoloadable.rb

Overview

Methods added to feature modules that include Autoloadable.

Instance Method Summary collapse

Instance Method Details

#included(base) ⇒ Object

Triggered when the feature is included in a user class.

Sets up for post-inclusion autoloading. The actual autoloading is deferred until after feature setup completes.

Parameters:

  • base (Class)

    the user class including this feature



32
33
34
35
36
37
38
# File 'lib/familia/features/autoloadable.rb', line 32

def included(base)
  # Call parent included method if it exists (defensive programming for mixed-in contexts)
  super if defined?(super)

  # No autoloading here - it's deferred to post_inclusion_autoload
  # to ensure the feature is fully set up before extension files are loaded
end

#post_inclusion_autoload(base, feature_name, options) ⇒ Object

Called by the feature system after the feature is fully included.

Uses const_source_location to determine where the base class is defined, then autoloads feature-specific extension files from that location.

Parameters:

  • base (Class)

    the class that included this feature

  • feature_name (Symbol)

    the name of the feature

  • options (Hash)

    feature options (unused but kept for compatibility)



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/familia/features/autoloadable.rb', line 48

def post_inclusion_autoload(base, feature_name, options)
  Familia.trace :FEATURE, nil, "[Autoloadable] post_inclusion_autoload called for #{feature_name} on #{base.name || base}", caller(1..1) if Familia.debug?

  # Get the source location via Ruby's built-in introspection
  source_location = nil

  # Check for named classes that can be looked up via const_source_location
  # Class#name always returns String or nil, so type check is redundant
  if base.name && !base.name.empty?
    begin
      location_info = Module.const_source_location(base.name)
      source_location = location_info&.first
      Familia.trace :FEATURE, nil, "[Autoloadable] Source location for #{base.name}: #{source_location}", caller(1..1) if Familia.debug?
    rescue NameError => e
      # Handle cases where the class name is not a valid constant name
      # This can happen in test environments with dynamically created classes
      Familia.trace :FEATURE, nil, "[Autoloadable] Cannot resolve source location for #{base.name}: #{e.message}", caller(1..1) if Familia.debug?
    end
  else
    Familia.trace :FEATURE, nil, "[Autoloadable] Skipping source location detection - base.name=#{base.name.inspect}", caller(1..1) if Familia.debug?
  end

  # Autoload feature-specific files if we have a valid source location
  if source_location && !source_location.include?('-e') # Skip eval/irb contexts
    Familia.trace :FEATURE, nil, "[Autoloadable] Calling autoload_feature_files with #{source_location}", caller(1..1) if Familia.debug?
    autoload_feature_files(source_location, base, feature_name.to_s.snake_case)
  else
    Familia.trace :FEATURE, nil, "[Autoloadable] Skipping autoload - no valid source location", caller(1..1) if Familia.debug?
  end
end