Class: RailsForge::Analyzers::RefactorAnalyzer

Inherits:
BaseAnalyzer
  • Object
show all
Defined in:
lib/railsforge/analyzers/refactor_analyzer.rb

Overview

RefactorAnalyzer provides refactoring suggestions

Defined Under Namespace

Classes: RefactorError

Constant Summary collapse

CONTROLLER_MAX_LINES =
150
CONTROLLER_MAX_METHODS =
10
MODEL_MAX_LINES =
200
MODEL_MAX_METHOD_LINES =
15

Class Method Summary collapse

Methods inherited from BaseAnalyzer

analyze, #analyze, #find_rails_app_path, find_rails_app_path

Class Method Details

.analyze_controllers(base_path = nil) ⇒ Object

Analyze controllers

Raises:



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/railsforge/analyzers/refactor_analyzer.rb', line 18

def self.analyze_controllers(base_path = nil)
  base_path ||= find_rails_app_path
  raise RefactorError, "Not in a Rails app" unless base_path

  controllers_dir = File.join(base_path, "app", "controllers")
  return [] unless Dir.exist?(controllers_dir)

  results = []
  Dir.glob(File.join(controllers_dir, "**", "*_controller.rb")).each do |file|
    result = analyze_file(file, :controller)
    results << result if result[:needs_refactoring]
  end
  results
end

.analyze_file(file_path, type) ⇒ Object



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
78
79
80
# File 'lib/railsforge/analyzers/refactor_analyzer.rb', line 50

def self.analyze_file(file_path, type)
  content = File.read(file_path)
  lines = content.lines.count
  methods = extract_methods(content)

  issues = []
  suggestions = []

  if type == :controller
    issues << "Exceeds #{CONTROLLER_MAX_LINES} lines" if lines > CONTROLLER_MAX_LINES
    issues << "Has #{methods.count} methods" if methods.count > CONTROLLER_MAX_METHODS
    suggestions << "Consider moving business logic to Service object" if lines > CONTROLLER_MAX_LINES
  else
    issues << "Exceeds #{MODEL_MAX_LINES} lines" if lines > MODEL_MAX_LINES
  end

  methods.each do |method|
    suggestions << "Method `#{method[:name]}` has #{method[:lines]} lines - consider extracting" if method[:lines] > MODEL_MAX_METHOD_LINES
  end

  {
    type: type,
    file: File.basename(file_path),
    path: file_path,
    lines: lines,
    methods: methods,
    issues: issues,
    suggestions: suggestions,
    needs_refactoring: issues.any? || suggestions.any?
  }
end

.analyze_models(base_path = nil) ⇒ Object

Analyze models

Raises:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/railsforge/analyzers/refactor_analyzer.rb', line 34

def self.analyze_models(base_path = nil)
  base_path ||= find_rails_app_path
  raise RefactorError, "Not in a Rails app" unless base_path

  models_dir = File.join(base_path, "app", "models")
  return [] unless Dir.exist?(models_dir)

  results = []
  Dir.glob(File.join(models_dir, "**", "*.rb")).each do |file|
    next if file.end_with?("_application.rb")
    result = analyze_file(file, :model)
    results << result if result[:needs_refactoring]
  end
  results
end

.extract_methods(content) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/railsforge/analyzers/refactor_analyzer.rb', line 82

def self.extract_methods(content)
  methods = []
  in_method = false
  method_lines = []

  content.lines.each do |line|
    if line =~ /\bdef\s+(\w+)/
      methods << { name: $1, lines: method_lines.count } if in_method
      in_method = true
      method_lines = [line]
    elsif in_method
      method_lines << line
      methods << { name: methods.last[:name], lines: method_lines.count } if line.strip == "end" && method_lines.count > 1
    end
  end

  methods
end


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/railsforge/analyzers/refactor_analyzer.rb', line 101

def self.print_report(results)
  puts "\nRefactoring Suggestions"
  puts "-" * 40

  if results.empty?
    puts "✓ No refactoring needed"
    return
  end

  results.each do |result|
    puts "#{result[:file]}"
    result[:issues].each { |i| puts "  - #{i}" }
    result[:suggestions].each { |s| puts "#{s}" }
  end
end