Class: RailsAiBridge::Introspectors::NonArModelsIntrospector

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_ai_bridge/introspectors/non_ar_models_introspector.rb

Overview

Discovers concrete Ruby classes under the logical +app/models+ Rails path that do not inherit from ActiveRecord::Base, so assistants can surface POJOs and service objects that would not appear in ActiveRecord model introspector.

After a best-effort eager load of every configured +app/models+ directory, entries are derived from +Object.const_source_location+ so anonymous or invalidly named classes are skipped.

Since:

  • 2.2.0

Constant Summary collapse

TAG =

Default label attached to each discovered non-AR class in tool and rules output.

Since:

  • 2.2.0

'POJO/Service'

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ NonArModelsIntrospector

Initializes the introspector for a Rails application.

Stores the provided Rails application, its root path, and a path resolver that maps configured model directories back to stable logical paths.

Parameters:

  • app (Rails::Application)

    host application whose +root+ and paths are used

Since:

  • 2.2.0



35
36
37
38
39
# File 'lib/rails_ai_bridge/introspectors/non_ar_models_introspector.rb', line 35

def initialize(app)
  @app = app
  @root = app.root.to_s
  @path_resolver = PathResolver.new(app)
end

Instance Method Details

#callHash

Builds the non-ActiveRecord model index for MCP and static rules.

Discovery uses every configured +app/models+ path rather than assuming the conventional directory exists.

Returns:

  • (Hash)

    Either:

    • { non_ar_models: Array<Hash> } where each Hash has keys :name, :relative_path, and :tag, or
    • { error: String } containing a sanitized, truncated error message.

Since:

  • 2.2.0



49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rails_ai_bridge/introspectors/non_ar_models_introspector.rb', line 49

def call
  eager_load!
  models_roots = models_roots_for_discovery
  return { non_ar_models: [] } if models_roots.empty?

  entries = {}
  models_roots.each { |models_root| collect_entries(models_root, entries) }

  { non_ar_models: entries.values.sort_by { |h| h[:name] } }
rescue StandardError => error
  { error: sanitize_error_message(error.message) }
end

#sanitize_error_message(message) ⇒ String

Produces a sanitized, truncated error message safe for external exposure.

Parameters:

  • message (String, nil)
    • The original error message which may contain file paths.

Returns:

  • (String)

    A message with filesystem paths replaced by "/[REDACTED]" and limited to 200 characters; returns "Introspection failed" if the input is nil or empty.

Since:

  • 2.2.0



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rails_ai_bridge/introspectors/non_ar_models_introspector.rb', line 66

def sanitize_error_message(message)
  return 'Introspection failed' if message.blank?

  # Remove potential file paths that could expose directory structure
  sanitized = message.gsub(%r{/[^\s]*/[^/\s]+}, '/[REDACTED]')

  # Limit length to prevent log flooding and information disclosure
  if sanitized.length > 200
    "#{sanitized[0...197]}..."
  else
    sanitized
  end
end