Class: Woods::Extractors::PoroExtractor
- Inherits:
-
Object
- Object
- Woods::Extractors::PoroExtractor
- Includes:
- SharedDependencyScanner, SharedUtilityMethods
- Defined in:
- lib/woods/extractors/poro_extractor.rb
Overview
PoroExtractor handles plain Ruby object extraction from app/models/.
Scans app/models/ for Ruby files that define classes which are NOT ActiveRecord descendants (those are handled by ModelExtractor). Captures value objects, form objects, CurrentAttributes subclasses, Struct.new wrappers, and any other non-AR class living alongside AR models.
Files under app/models/concerns/ are excluded — those are handled by ConcernExtractor. Module-only files are also excluded.
Constant Summary collapse
- MODELS_GLOB =
Glob pattern for all Ruby files in app/models/ (recursive).
'app/models/**/*.rb'- CONCERNS_SEGMENT =
Subdirectory to exclude — handled by ConcernExtractor.
'/concerns/'
Constants included from SharedDependencyScanner
SharedDependencyScanner::FORM_ACTION_HELPER, SharedDependencyScanner::ROUTE_HELPER_PATTERN
Instance Method Summary collapse
-
#extract_all ⇒ Array<ExtractedUnit>
Extract all PORO units from app/models/.
-
#extract_poro_file(file_path, ar_names: Set.new) ⇒ ExtractedUnit?
Extract a single PORO file.
-
#initialize ⇒ PoroExtractor
constructor
A new instance of PoroExtractor.
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
#initialize ⇒ PoroExtractor
Returns a new instance of PoroExtractor.
35 36 37 |
# File 'lib/woods/extractors/poro_extractor.rb', line 35 def initialize @models_dir = Rails.root.join('app/models') end |
Instance Method Details
#extract_all ⇒ Array<ExtractedUnit>
Extract all PORO units from app/models/.
Filters out ActiveRecord descendants by name so we don’t duplicate what ModelExtractor already produces. Concerns/ subdir is also skipped.
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/woods/extractors/poro_extractor.rb', line 45 def extract_all return [] unless @models_dir.directory? ar_names = ActiveRecord::Base.descendants.filter_map(&:name).to_set Dir[Rails.root.join(MODELS_GLOB)].filter_map do |file| next if file.include?(CONCERNS_SEGMENT) extract_poro_file(file, ar_names: ar_names) end end |
#extract_poro_file(file_path, ar_names: Set.new) ⇒ ExtractedUnit?
Extract a single PORO file.
Returns nil if the file is not a PORO (e.g., module-only, no class or PORO pattern found, or the inferred class is an AR descendant).
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/woods/extractors/poro_extractor.rb', line 65 def extract_poro_file(file_path, ar_names: Set.new) source = File.read(file_path) return nil unless poro_file?(source) return nil if module_only?(source) class_name = infer_class_name(file_path, source) return nil unless class_name return nil if ar_names.include?(class_name) unit = ExtractedUnit.new( type: :poro, 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 PORO #{file_path}: #{e.}") nil end |