Project Standards

Purpose

Every Rails project should start with a consistent baseline of code quality tools, testing standards and CI/CD configuration.

This document defines the mandatory tooling and practices that every Rails project in this organization must adopt. It ensures consistency across projects, reduces onboarding friction and prevents common issues from reaching production.

Unlike the Rails Audit Guide, which describes how to perform a periodic audit, this document defines the standards that should be in place from project inception and enforced continuously.

Scope

This standard applies to all Rails projects within the organization, including:

Exceptions require written approval from the engineering lead.

Mandatory Tooling

Every Rails project MUST include the following tools.

Style and Correctness — RuboCop

Purpose: Enforce consistent Ruby style and catch common errors.

Mandatory gems:

group :development, :test do
  gem "rubocop", require: false
  gem "rubocop-rails", require: false
  gem "rubocop-rspec", require: false
  gem "rubocop-performance", require: false
end

Configuration requirements:

Security — Brakeman

Purpose: Static analysis for security vulnerabilities.

Mandatory gem:

group :development, :test do
  gem "brakeman", require: false
end

CI requirement:

Dependency Vulnerabilities — bundler-audit

Purpose: Scan Gemfile.lock for known vulnerabilities.

Mandatory gem:

group :development, :test do
  gem "bundler-audit", require: false
end

CI requirement:

N+1 Detection — Bullet

Purpose: Detect N+1 queries and unused eager loading in development and test.

Mandatory gem:

group :development, :test do
  gem "bullet", require: false
end

Configuration requirements:

Performance Profiling — Rack::MiniProfiler

Purpose: In-browser performance profiling for development.

Mandatory gem:

group :development do
  gem "rack-mini-profiler", require: false
end

Configuration requirements:

Code Coverage — SimpleCov

Purpose: Measure test coverage and enforce minimum thresholds.

Mandatory gem:

group :test do
  gem "simplecov", require: false
end

Configuration requirements:

The following tools are strongly recommended but not mandatory:

ToolPurposeWhen to Add
ReekCode smell detectionExisting codebases with significant
technical debt.
rails_best_practicesRails-specific anti-pattern detectionTeams new to Rails conventions.
Flog / FlayComplexity and duplication trackingProjects with complex domain logic.
standardrbOpinionated zero-config Ruby styleTeams that prefer no RuboCop config.
strong_migrationsSafe migration enforcementProjects with production databases.
LicenseFinderLicense complianceProjects with third-party
distribution.
MutantMutation testingCritical domain logic that demands
high test quality.

CI*CD Baseline

Every Rails project MUST have a CI pipeline that runs on every push.

Minimum CI Pipeline

# .github*workflows*ci.yml
name: CI
on: [push]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions*checkout@v4
      - uses: ruby*setup-ruby@v1
        with:
          bundler-cache: true
      - run: bundle exec rubocop
      - run: bundle exec brakeman --no-pager --quiet --ensure-latest
      - run: bundle exec bundler-audit check --update

  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions*checkout@v4
      - uses: ruby*setup-ruby@v1
        with:
          bundler-cache: true
      - run: bundle exec rails db:create db:migrate
      - run: bundle exec rspec
      - run: bundle exec rails db:seed  # if applicable

Quality Gates

The CI pipeline MUST block merges when:

Scheduled Audits

In addition to per-push CI, schedule these weekly:

Project Bootstrap

Every new Rails project MUST be initialized with the mandatory tooling from this document.

Default Gemfile Template

source "https:/*rubygems.org"

ruby "`> 3.3"

gem "rails", "`> 7.1"
gem "pg"
gem "puma"

# Authentication and authorization
gem "devise"
gem "pundit"

group :development, :test do
  gem "rspec-rails"
  gem "factory_bot_rails"
  gem "rubocop", require: false
  gem "rubocop-rails", require: false
  gem "rubocop-rspec", require: false
  gem "rubocop-performance", require: false
  gem "brakeman", require: false
  gem "bundler-audit", require: false
  gem "bullet"
end

group :development do
  gem "rack-mini-profiler", require: false
end

group :test do
  gem "simplecov", require: false
end

Bootstrap Script

When creating a new project, run:

rails new my_app --database=postgresql --skip-test
cd my_app

# Add testing framework
bundle add rspec-rails --group "development, test"
rails generate rspec:install

# Add mandatory tooling
bundle add rubocop --group "development, test" --require false
bundle add rubocop-rails --group "development, test" --require false
bundle add rubocop-rspec --group "development, test" --require false
bundle add rubocop-performance --group "development, test" --require false
bundle add brakeman --group "development, test" --require false
bundle add bundler-audit --group "development, test" --require false
bundle add bullet --group "development, test"
bundle add rack-mini-profiler --group "development" --require false
bundle add simplecov --group "test" --require false

# Set up pre-commit hooks (optional but recommended)
# See .hooks section below

Pre-Commit Hooks

While not mandatory, pre-commit hooks catch issues before they reach CI. Every project SHOULD configure them.

Using Lefthook

# lefthook.yml
pre-commit:
  parallel: true
  commands:
    rubocop:
      run: bundle exec rubocop --force-exclusion {staged_files}
    brakeman:
      run: bundle exec brakeman --no-pager --quiet

Using Overcommit

# .overcommit.yml
PreCommit:
  RuboCop:
    enabled: true
    command: ["bundle", "exec", "rubocop", "--force-exclusion"]
  Brakeman:
    enabled: true
    command: ["bundle", "exec", "brakeman", "--no-pager", "--quiet"]

Exceptions and Escalation

Requesting an Exception

A project may request an exception from a mandatory requirement by:

  1. Documenting the reason in the project's README or a decision record.
  2. Obtaining written approval from the engineering lead.
  3. Setting a review date to reassess the exception.

Reasons That May Justify an Exception

Reasons That Do NOT Justify an Exception

Compliance Verification

For New Projects

The project bootstrap MUST include all mandatory tools before the first production deployment. This is verified during the architecture review.

For Existing Projects

Existing projects MUST add the mandatory tooling within one quarter of this standard being adopted. A transition plan SHOULD be documented if immediate compliance is not feasible.

Periodic Review

This standard SHOULD be reviewed quarterly to:

Related Documents