Class: RailsAiContext::Introspectors::ModelIntrospector
- Inherits:
-
Object
- Object
- RailsAiContext::Introspectors::ModelIntrospector
- Defined in:
- lib/rails_ai_context/introspectors/model_introspector.rb
Overview
Extracts ActiveRecord model metadata using a hybrid approach:
- Rails reflection for runtime data (associations, validations, enums, table info)
- Prism AST for source-level declarations (scopes, callbacks, macros, methods)
The AST layer replaces all regex/scan/match? source parsing with Prism::Dispatcher-based single-pass extraction via SourceIntrospector.
Constant Summary collapse
- EXCLUDED_CALLBACKS =
%w[autosave_associated_records_for].freeze
Instance Attribute Summary collapse
-
#app ⇒ Object
readonly
Returns the value of attribute app.
-
#config ⇒ Object
readonly
Returns the value of attribute config.
Instance Method Summary collapse
-
#call ⇒ Hash
Model metadata keyed by model name.
-
#initialize(app) ⇒ ModelIntrospector
constructor
A new instance of ModelIntrospector.
-
#static_call ⇒ Object
Static tier: models are discovered by globbing every model directory PathResolver resolves (conventional app/models, packs, engines, and configured extras) and parsed with the source listeners; nothing is constantized.
Constructor Details
#initialize(app) ⇒ ModelIntrospector
Returns a new instance of ModelIntrospector.
16 17 18 19 |
# File 'lib/rails_ai_context/introspectors/model_introspector.rb', line 16 def initialize(app) @app = app @config = RailsAiContext.configuration end |
Instance Attribute Details
#app ⇒ Object (readonly)
Returns the value of attribute app.
12 13 14 |
# File 'lib/rails_ai_context/introspectors/model_introspector.rb', line 12 def app @app end |
#config ⇒ Object (readonly)
Returns the value of attribute config.
12 13 14 |
# File 'lib/rails_ai_context/introspectors/model_introspector.rb', line 12 def config @config end |
Instance Method Details
#call ⇒ Hash
Returns model metadata keyed by model name.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rails_ai_context/introspectors/model_introspector.rb', line 22 def call eager_load_models! models = discover_models result = models.each_with_object({}) do |model, hash| hash[model.name] = extract_model_details(model) rescue => e hash[model.name] = { error: e. } end # A hybrid app (ActiveRecord primary, Mongoid gem present too) has # documents that AR reflection can never see - they don't descend # from ActiveRecord::Base. Supplement rather than replace, so a # pure-AR model in a hybrid app keeps its full reflection-based # details instead of being reduced to Mongoid's blanket static pass. if RailsAiContext::AppKind.mongoid?(app.root) mongoid_static_models.each do |class_name, details| next if result.key?(class_name) next unless details[:mongoid] result[class_name] = details end end result end |
#static_call ⇒ Object
Static tier: models are discovered by globbing every model directory PathResolver resolves (conventional app/models, packs, engines, and configured extras) and parsed with the source listeners; nothing is constantized. The table name is inferred from the class name (Rails convention), which is why every entry is tagged STATIC rather than VERIFIED - custom table_name= calls surface in :macros but are not resolved. When the same class name is found in more than one directory, the first discovery wins.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/rails_ai_context/introspectors/model_introspector.rb', line 57 def static_call return mongoid_static_models if RailsAiContext::AppKind.mongoid?(app.root) RailsAiContext::PathResolver.model_dirs(app.root).each_with_object({}) do |models_dir, result| Dir.glob(File.join(models_dir, "**", "*.rb")).sort.each do |path| relative = path.sub("#{models_dir}/", "").sub(/\.rb\z/, "") next if relative == "application_record" || relative.start_with?("concerns/") class_name = relative.camelize next if result.key?(class_name) next if config.excluded_models.include?(class_name) begin next if File.size(path) > RailsAiContext.configuration.max_file_size result[class_name] = static_model_details(path, class_name) rescue => e result[class_name] = { error: e. } end end end end |