Class: QueryGuard::CLI::Formatter
- Inherits:
-
Object
- Object
- QueryGuard::CLI::Formatter
- Defined in:
- lib/query_guard/cli/formatter.rb
Overview
Formats findings for terminal output or JSON Provides clean, developer-friendly output with:
- Severity and type grouping
- Clear recommendations and action items
- Index suggestions and migration steps
- Summary with detailed counts
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ Formatter
constructor
A new instance of Formatter.
- #print_finding(finding, indent: " ") ⇒ Object
- #print_finding_context(finding, indent) ⇒ Object
- #print_findings(findings, title = "Analysis Results", command = 'analyze', path = '.') ⇒ Object
- #print_index_suggestions(finding, indent) ⇒ Object
- #print_json(findings, command = 'analyze', path = '.') ⇒ Object
- #print_migration_steps(finding, indent) ⇒ Object
- #print_recommendations(finding, indent) ⇒ Object
- #print_severity_section(severity, findings) ⇒ Object
- #print_text(findings, title) ⇒ Object
- #print_type_group(type_key, findings) ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ Formatter
Returns a new instance of Formatter.
12 13 14 15 16 |
# File 'lib/query_guard/cli/formatter.rb', line 12 def initialize( = {}) = @json = [:json] || [:format] == 'json' || false @verbose = [:verbose] || false end |
Instance Method Details
#print_finding(finding, indent: " ") ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/query_guard/cli/formatter.rb', line 78 def print_finding(finding, indent: " ") # Title and location puts "\n#{indent}#{finding[:title]}" # File and line info if finding[:file_path] location = "#{finding[:file_path]}" location += ":#{finding[:line_number]}" if finding[:line_number] puts "#{indent} š #{location}" end # Description if finding[:description] puts "#{indent} #{finding[:description]}" end # Metadata context (table, operation, escalation) print_finding_context(finding, indent) # Recommendations (primary) print_recommendations(finding, indent) # Special metadata sections: indexes, migration steps, strategies print_index_suggestions(finding, indent) print_migration_steps(finding, indent) # Verbose debug metadata if @verbose && finding[:metadata] && !finding[:metadata].empty? puts "#{indent} [Debug] #{finding[:metadata].inspect}" end end |
#print_finding_context(finding, indent) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/query_guard/cli/formatter.rb', line 110 def print_finding_context(finding, indent) = finding[:metadata] || {} # Table context if [:table_name] rows = [:estimated_table_rows] rows_str = rows ? " (#{format_row_count(rows)} rows)" : "" puts "#{indent} šļø Table: #{metadata[:table_name]}#{rows_str}" end # Operation context if [:operation] puts "#{indent} āļø Operation: #{metadata[:operation]}" end # Escalation if [:severity_escalated] original = [:original_severity] reason = [:escalation_reason] puts "#{indent} ā¬ļø Escalated from #{original}: #{reason}" end # Risk level if [:risk_level] puts "#{indent} Risk Level: #{metadata[:risk_level]}" end end |
#print_findings(findings, title = "Analysis Results", command = 'analyze', path = '.') ⇒ Object
18 19 20 21 22 23 24 |
# File 'lib/query_guard/cli/formatter.rb', line 18 def print_findings(findings, title = "Analysis Results", command = 'analyze', path = '.') if @json print_json(findings, command, path) else print_text(findings, title) end end |
#print_index_suggestions(finding, indent) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/query_guard/cli/formatter.rb', line 150 def print_index_suggestions(finding, indent) = finding[:metadata] || {} # Check for single index suggestion if [:index_sql] puts "#{indent} š§ Suggested Index:" puts "#{indent} #{metadata[:index_sql]}" elsif [:suggested_indexes] # Multiple index suggestions puts "#{indent} š§ Suggested Indexes:" Array([:suggested_indexes]).each do |idx_sql| puts "#{indent} #{idx_sql}" end end end |
#print_json(findings, command = 'analyze', path = '.') ⇒ Object
184 185 186 187 188 189 190 191 192 |
# File 'lib/query_guard/cli/formatter.rb', line 184 def print_json(findings, command = 'analyze', path = '.') reporter = JsonReporter.new( findings: findings, command: command, path: path, options: ) puts reporter.generate end |
#print_migration_steps(finding, indent) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/query_guard/cli/formatter.rb', line 166 def print_migration_steps(finding, indent) = finding[:metadata] || {} # Migration step-by-step guidance if [:migration_steps] puts "#{indent} š Migration Steps:" Array([:migration_steps]).each_with_index do |step, i| puts "#{indent} #{i + 1}. #{step}" end end # Safe rollout strategy if [:safe_rollout_strategy] puts "#{indent} š”ļø Safe Rollout Strategy:" puts "#{indent} #{metadata[:safe_rollout_strategy]}" end end |
#print_recommendations(finding, indent) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/query_guard/cli/formatter.rb', line 138 def print_recommendations(finding, indent) # Show recommendations as action items recommendations = Array(finding[:recommendation]) if recommendations.any? puts "#{indent} ā Recommended Actions:" recommendations.each do |rec| puts "#{indent} - #{rec}" end end end |
#print_severity_section(severity, findings) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/query_guard/cli/formatter.rb', line 50 def print_severity_section(severity, findings) icon = severity_icon(severity) color = severity_color(severity) label = severity.to_s.upcase puts "\n#{icon} #{color}#{label}#{reset_color} (#{findings.length})" puts "-" * 60 # Group by type within severity by_type = findings.group_by { |f| "#{f[:analyzer_name]}:#{f[:rule_name]}" } by_type.each do |type_key, type_findings| print_type_group(type_key, type_findings) end end |
#print_text(findings, title) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/query_guard/cli/formatter.rb', line 26 def print_text(findings, title) puts "\n" + "=" * 60 puts title puts "=" * 60 if findings.empty? puts "\nā No issues found!\n" return end # Group findings by severity, then by type by_severity = findings.group_by { |f| f[:severity] } # Print in order severity_order = [:critical, :error, :warn, :info] severity_order.each do |severity| next unless by_severity[severity] print_severity_section(severity, by_severity[severity]) end print_summary(findings) end |
#print_type_group(type_key, findings) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/query_guard/cli/formatter.rb', line 66 def print_type_group(type_key, findings) # Print type header when multiple findings of same type if findings.length == 1 print_finding(findings.first) else puts "\n [#{type_key}] (#{findings.length} findings)" findings.each do |finding| print_finding(finding, indent: " ") end end end |