Rails application health diagnostics. Scans your codebase, surfaces structural issues, and tells you exactly what to fix.
Rails apps accumulate structural debt invisibly. Fat controllers, missing indexes, unguarded SQL, no specs for business-critical services — none of it surfaces until something breaks in production. By then the cost is high and the cause is buried.
Most teams only discover these problems during an audit, a security review, or an incident.
railsforge doctorRuns a full diagnostic scan across your Rails app. Returns a health score and every detected issue, ranked by severity, with a concrete fix for each one.
RailsForge Health Report
─────────────────────────────��────────────────────
Score: 61/100
Issues: 9 total
HIGH (2)
[security]
app/controllers/users_controller.rb:42 — SQL Injection: User.where("name = '#{params[:name]}'")
→ Use parameterized queries: Model.where(column: value)
[performance]
app/controllers/posts_controller.rb:18 — N+1 Query: @posts.each do |post| post.comments.find
→ Use eager loading: includes(:association) or preload(:association)
MEDIUM (4)
[controller]
app/controllers/admin_controller.rb — AdminController has 214 lines (max 150)
→ Extract business logic to Service objects
[database]
db/schema.rb — Table `events` has datetime columns without an index
→ add_index :events, :created_at
[refactor]
app/models/user.rb — User has 267 lines (max 200)
→ Consider extracting concerns or service objects
app/models/order.rb — Method `process_payment` has 43 lines
→ Consider extracting to a private method or service
LOW (3)
[spec]
app/service/invoice_generator.rb — Service `invoice_generator` has no spec
→ Create spec/services/invoice_generator_spec.rb
app/service/payment_processor.rb — Service `payment_processor` has no spec
→ Create spec/services/payment_processor_spec.rb
[controller]
app/controllers/api/v1/orders_controller.rb — OrdersController has 13 methods (max 10)
→ Consider splitting into focused controllers
railsforge doctor --format=jsonReturns structured output for CI pipelines and automated tooling:
{
"score": 61,
"issues": [
{
"analyzer": "security",
"type": "sql_injection",
"severity": "high",
"file": "app/controllers/users_controller.rb",
"line": 42,
"message": "SQL Injection: User.where(\"name = '#{params[:name]}'\")",
"suggestion": "Use parameterized queries: Model.where(column: value)"
}
],
"summary": {
"total": 9,
"by_severity": {
"critical": 0,
"high": 2,
"medium": 4,
"low": 3,
"info": 0
}
}
}All five severity keys are always present, even when zero. Score is always an integer. Output is deterministic.
RailsForge provides signal. CI decides consequences.
railsforge doctor --format=json | jq '.score'RailsForge always exits 0 on a successful run. Your CI script owns the pass/fail logic.
name: RailsForge Health Check
on: [push, pull_request]
jobs:
railsforge:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.2
- name: Install RailsForge
run: gem install railsforge
- name: Run RailsForge
run: |
score=$(railsforge doctor --format=json | jq '.score')
echo "Score: $score"
if [ "$score" -lt 80 ]; then
echo "RailsForge score below threshold"
exit 1
fi- Security — SQL injection, XSS, weak cryptography, sensitive data exposure
- Performance — N+1 queries, missing database indexes, inefficient query patterns
- Architecture — Fat controllers, fat models, methods that exceed complexity thresholds
- Test coverage — Service objects, queries, jobs, policies with no corresponding spec
- Refactoring opportunities — Long methods, oversized files
gem install railsforgeOr in your Gemfile:
group :development do
gem 'railsforge', require: false
endRequires Ruby 3.0+.
Optional .railsforgerc in your project root:
analyzers:
controller_max_lines: 150
controller_max_methods: 10
model_max_lines: 200
model_max_method_lines: 15Analyze reality. Don't prescribe structure.
MIT