Rails Doctor

A Rails health report for developers, CI, and AI coding agents. Generated from normalized scanner findings, runtime signals, and Rails-specific checks.

Overall health
0
Changed files: 86 · Confidence: 100%
Critical1
High10
Medium10
Coverage48.00%
Skipped0
Duration1497ms

Coverage

Line coverage48.00%
Line threshold90.00%
Covered lines12/25
Branch coverage50.00%
FileLine coverageCoveredThreshold
app/controllers/posts_controller.rb 22.22% 2/9 80.00%
app/models/post.rb 44.44% 4/9 80.00%

Top Fixes

critical
SQL Injection: Possible SQL injection
app/models/post.rb:8

Review Brakeman guidance: https://brakemanscanner.org/docs/warning_types/sql_injection/

high
rack: Example vulnerability
Gemfile.lock

Update rack to a patched version and rerun Bundler Audit.

high
Prosopite: N+1 queries detected for Post => [:user]

Fix the N+1 query by eager loading or adjusting the query path exercised by tests.

high
posts.user_id has no index
db/schema.rb

Add an index for the foreign key column to avoid slow association lookups.

high
users.email has a Rails uniqueness validation without a unique database index
app/models/user.rb

Back uniqueness validations with a unique index to prevent race-condition duplicates.

high
Routes reference missing ghosts_controller.rb
config/routes.rb

Create the controller or remove/rename the route.

high
Route points to missing posts#create
app/controllers/posts_controller.rb

Implement the action or update/remove the route.

high
Route points to missing posts#destroy
app/controllers/posts_controller.rb

Implement the action or update/remove the route.

high
Route points to missing posts#edit
app/controllers/posts_controller.rb

Implement the action or update/remove the route.

high
Route points to missing posts#new
app/controllers/posts_controller.rb

Implement the action or update/remove the route.

high
Route points to missing posts#update
app/controllers/posts_controller.rb

Implement the action or update/remove the route.

medium
DEPRECATION WARNING: old API is deprecated

Resolve deprecation warnings before framework or gem upgrades make them failures.

Agent Brief

Coverage: 48.00% lines

## Coverage
- app/controllers/posts_controller.rb: 22.22% lines (2/9)
- app/models/post.rb: 44.44% lines (4/9)

## Findings
- critical: Fix this security finding with the smallest behavior-preserving change. Prefer framework-safe APIs and add regression tests.
- high: Update the vulnerable gem conservatively, refresh the lockfile, and run the test suite.
- high: Use includes/preload/eager_load or query restructuring. Verify with the same test command.
- high: Create a migration that adds an index on posts.user_id. For PostgreSQL production apps, prefer a concurrent index path compatible with strong_migrations.
- high: Add a unique index migration for users.email, handle existing duplicate data if necessary, and rerun tests.
- high: Align routes with real controller names. Prefer removing stale routes over creating empty controllers.
- high: Do not add an empty action. Determine the intended route behavior, then implement or remove the stale route.
- high: Do not add an empty action. Determine the intended route behavior, then implement or remove the stale route.
- high: Do not add an empty action. Determine the intended route behavior, then implement or remove the stale route.
- high: Do not add an empty action. Determine the intended route behavior, then implement or remove the stale route.
- high: Do not add an empty action. Determine the intended route behavior, then implement or remove the stale route.
- medium: Update the deprecated API usage and add a regression test when behavior could change.

Tool Run Notes

rubocop
Status: completed_with_findings · Exit: 1

The tool exited nonzero and Rails Doctor normalized actionable findings from its output.

brakeman
Status: completed_with_findings · Exit: 3

The tool exited nonzero and Rails Doctor normalized actionable findings from its output.

bundler_audit
Status: completed_with_findings · Exit: 1

The tool exited nonzero and Rails Doctor normalized actionable findings from its output.

reek
Status: completed_with_findings · Exit: 2

The tool exited nonzero and Rails Doctor normalized actionable findings from its output.

dependency_freshness
Status: completed_with_findings · Exit: 1

The tool exited nonzero and Rails Doctor normalized actionable findings from its output.

Findings

SeverityToolCategoryLocationFinding
medium rubocop lint app/models/post.rb:6 Rails/TimeZone: Use Time.current instead of Time.now.
Fix the RuboCop offense or document why this cop should be configured differently.
critical brakeman security app/models/post.rb:8 SQL Injection: Possible SQL injection
Review Brakeman guidance: https://brakemanscanner.org/docs/warning_types/sql_injection/
high bundler_audit dependency-security Gemfile.lock rack: Example vulnerability
Update rack to a patched version and rerun Bundler Audit.
medium reek code-smell app/models/post.rb:4 TooManyStatements: has the smell of too many statements
Refactor the local smell without broad behavior changes.
low strong_migrations migration-safety config/initializers/strong_migrations.rb strong_migrations is installed but no initializer was found
Generate or review the Strong Migrations initializer so project-specific safety settings are explicit.
high rails_checks database-integrity db/schema.rb posts.user_id has no index
Add an index for the foreign key column to avoid slow association lookups.
high rails_checks database-integrity app/models/user.rb users.email has a Rails uniqueness validation without a unique database index
Back uniqueness validations with a unique index to prevent race-condition duplicates.
high rails_checks routing config/routes.rb Routes reference missing ghosts_controller.rb
Create the controller or remove/rename the route.
high rails_checks routing app/controllers/posts_controller.rb Route points to missing posts#create
Implement the action or update/remove the route.
high rails_checks routing app/controllers/posts_controller.rb Route points to missing posts#destroy
Implement the action or update/remove the route.
high rails_checks routing app/controllers/posts_controller.rb Route points to missing posts#edit
Implement the action or update/remove the route.
high rails_checks routing app/controllers/posts_controller.rb Route points to missing posts#new
Implement the action or update/remove the route.
medium rails_checks routing app/controllers/posts_controller.rb posts#show has no matching template or explicit response
Add a template or explicit render/redirect/head response.
high rails_checks routing app/controllers/posts_controller.rb Route points to missing posts#update
Implement the action or update/remove the route.
low rails_checks dead-code app/controllers/posts_controller.rb posts#archive is not referenced by simple route analysis
Review whether this action is reached by custom routing or can be removed.
medium rails_checks technical-debt app/models/post.rb 1 TODO/FIXME/HACK marker in 10 lines
Convert stale markers into tracked work or resolve them while the context is fresh.
medium test_runner deprecation 1 DEPRECATION WARNING: old API is deprecated
Resolve deprecation warnings before framework or gem upgrades make them failures.
high test_runner runtime-n-plus-one 2 Prosopite: N+1 queries detected for Post => [:user]
Fix the N+1 query by eager loading or adjusting the query path exercised by tests.
medium test_coverage test-coverage Line coverage 48.00% is below the 90.00% threshold
Add tests for uncovered application code, starting with the lowest-coverage files.
medium test_coverage test-coverage app/controllers/posts_controller.rb app/controllers/posts_controller.rb line coverage 22.22% is below the 80.00% per-file threshold
Add focused tests that exercise the uncovered behavior in this file.
medium test_coverage test-coverage app/models/post.rb app/models/post.rb line coverage 44.44% is below the 80.00% per-file threshold
Add focused tests that exercise the uncovered behavior in this file.
medium flog complexity app/models/post.rb:4 High complexity score 32.5 for Post#publish!
Extract simpler methods or objects around the complex branch.
medium flay duplication app/models/post.rb:4 Similar code group 1 across app/models/post.rb:4, app/models/user.rb:2
Review whether this duplication is intentional. Extract shared behavior only if the abstraction is clear.
low dependency_freshness dependency-freshness Gemfile.lock brakeman appears to be outdated
Review the update risk and update in a separate dependency-focused change.
low dependency_freshness dependency-freshness Gemfile.lock bundler-audit appears to be outdated
Review the update risk and update in a separate dependency-focused change.
low dependency_freshness dependency-freshness Gemfile.lock flay appears to be outdated
Review the update risk and update in a separate dependency-focused change.
low dependency_freshness dependency-freshness Gemfile.lock flog appears to be outdated
Review the update risk and update in a separate dependency-focused change.
low dependency_freshness dependency-freshness Gemfile.lock prosopite appears to be outdated
Review the update risk and update in a separate dependency-focused change.
low dependency_freshness dependency-freshness Gemfile.lock rails appears to be outdated
Review the update risk and update in a separate dependency-focused change.
low dependency_freshness dependency-freshness Gemfile.lock rubocop appears to be outdated
Review the update risk and update in a separate dependency-focused change.
low dependency_freshness dependency-freshness Gemfile.lock rubocop-rails appears to be outdated
Review the update risk and update in a separate dependency-focused change.
low dependency_freshness dependency-freshness Gemfile.lock strong_migrations appears to be outdated
Review the update risk and update in a separate dependency-focused change.

Hotspots

FileScoreFindingsChurnChangedSummary
app/controllers/posts_controller.rb 42 8 0 false Inherited file with 8 findings across routing, dead-code, test-coverage.
app/models/post.rb 33 7 0 false Inherited file with 7 findings across lint, security, code-smell, technical-debt, test-coverage, complexity, duplication.
Gemfile.lock 29 10 3 true Changed file with 10 findings across dependency-security, dependency-freshness.
db/schema.rb 7 1 0 false Inherited file with 1 finding across database-integrity.
app/models/user.rb 7 1 0 false Inherited file with 1 finding across database-integrity.
config/routes.rb 7 1 0 false Inherited file with 1 finding across routing.
config/initializers/strong_migrations.rb 1 1 0 false Inherited file with 1 finding across migration-safety.

Skipped Tools

No tools were skipped.

Raw Tool Output

rubocop · completed_with_findings · exit 1
{"files":[{"path":"app/models/post.rb","offenses":[{"severity":"warning","message":"Use Time.current instead of Time.now.","cop_name":"Rails/TimeZone","location":{"line":6}}]}]}
\n
brakeman · completed_with_findings · exit 3
{"warnings":[{"warning_type":"SQL Injection","message":"Possible SQL injection","file":"app/models/post.rb","line":8,"confidence":"High","fingerprint":"abc123","link":"https://brakemanscanner.org/docs/warning_types/sql_injection/"}]}
\n
bundler_audit · completed_with_findings · exit 1
{"results":[{"gem":{"name":"rack"},"advisory":{"id":"CVE-2099-0001","title":"Example vulnerability","criticality":"high","url":"https://example.test/advisory"}}]}
\n
zeitwerk · completed · exit 0
Hold on, I am eager loading the application.
All is good!
\n
reek · completed_with_findings · exit 2
[{"context":"Post#publish!","lines":[4],"message":"has the smell of too many statements","smell_type":"TooManyStatements","source":"app/models/post.rb"}]
\n
test_runner · completed_with_findings · exit 0
DEPRECATION WARNING: old API is deprecated
Prosopite: N+1 queries detected for Post => [:user]
\n
flog · completed_with_findings · exit 0
  32.5 Post#publish! app/models/post.rb:4
\n
flay · completed_with_findings · exit 0
Similar code found in :iter (mass = 42)
  app/models/post.rb:4
  app/models/user.rb:2
\n
dependency_freshness · completed_with_findings · exit 1
brakeman (newest 8.0.4, installed 7.0.0)
bundler-audit (newest 0.9.3, installed 0.9.0)
flay (newest 2.14.4, installed 2.13.3)
flog (newest 4.9.4, installed 4.8.0)
prosopite (newest 2.2.0, installed 1.4.0)
rails (newest 8.1.3, installed 8.0.0, requested ~> 8.0)
rubocop (newest 1.87.0, installed 1.70.0)
rubocop-rails (newest 2.35.3, installed 2.28.0)
strong_migrations (newest 2.8.0, installed 2.0.0)
\nFetching gem metadata from https://rubygems.org/..........
Resolving dependencies...