in doc-architect/doc-architect-core/src/main/java/com/docarchitect/core/scanner/impl/ruby/RailsApiScanner.java [278:358]
private FallbackParsingStrategy<ControllerData> createFallbackStrategy(Path rootPath) {
return (file, content) -> {
List<ControllerData> results = new ArrayList<>();
if (!content.contains("Controller")) {
return results;
}
// Extract class definition
Matcher classMatcher = CLASS_PATTERN.matcher(content);
if (!classMatcher.find()) {
return results;
}
String className = classMatcher.group(1);
String superclass = classMatcher.group(2);
// Only process controller classes
if (!className.endsWith(CONTROLLER_SUFFIX)) {
return results;
}
if (!superclass.contains("ApplicationController") &&
!superclass.contains("ActionController")) {
return results;
}
// Create component
String componentId = IdGenerator.generate(className);
String relativePath = rootPath.relativize(file).toString();
Map<String, String> metadata = new HashMap<>();
metadata.put("file", relativePath);
metadata.put("language", Technologies.RUBY);
metadata.put("framework", "Rails");
metadata.put("superclass", superclass);
metadata.put("parsing", "regex-fallback");
Component component = new Component(
componentId,
className,
ComponentType.SERVICE,
null,
Technologies.RUBY,
relativePath,
metadata
);
// Extract methods
String resourcePath = extractResourcePath(className);
List<ApiEndpoint> endpoints = new ArrayList<>();
Matcher methodMatcher = METHOD_PATTERN.matcher(content);
while (methodMatcher.find()) {
String methodName = methodMatcher.group(1);
// Skip private/protected markers and non-action methods
if (methodName.equals("private") || methodName.equals("protected") ||
methodName.equals("public") || methodName.startsWith("_")) {
continue;
}
ApiEndpoint endpoint = createApiEndpoint(
methodName,
resourcePath,
componentId
);
if (endpoint != null) {
endpoints.add(endpoint);
}
}
if (!endpoints.isEmpty()) {
results.add(new ControllerData(component, endpoints));
log.debug("Fallback parsing found {} endpoints in {}", endpoints.size(), file.getFileName());
}
return results;
};
}