Claude Code Plugins

Community-maintained marketplace

Feedback

rails-ai:project-setup

@zerobearing2/rails-ai
12
0

Setting up and configuring Rails 8+ projects - Gemfile dependencies, environment config, credentials, initializers, Docker, RuboCop, project validation

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name rails-ai:project-setup
description Setting up and configuring Rails 8+ projects - Gemfile dependencies, environment config, credentials, initializers, Docker, RuboCop, project validation

Project Setup & Configuration

Set up new Rails 8+ projects with required dependencies, configure environments for development/test/production, and validate existing projects against rails-ai standards.

- Setting up new Rails 8+ applications from scratch - Validating existing Rails projects against rails-ai standards - Auditing project setup (checking for TEAM_RULES.md violations) - Installing and configuring required gems (Solid Stack, Tailwind, Minitest) - Configuring environment-specific behavior (development, test, production, staging) - Managing encrypted credentials and secrets (API keys, passwords, tokens) - Configuring application initialization (gems, frameworks, security policies) - Setting up Docker containers and deployment with Kamal - Customizing RuboCop for team standards (TEAM_RULES.md Rules #16, #20) - Managing feature flags and environment variables

Note: During project verification, this skill coordinates with domain skills (jobs, testing, security, styling) to ensure comprehensive validation against current standards.

- **Environment Isolation** - Separate configs prevent production bugs from dev settings - **Security** - Encrypted credentials (AES-256), never commit secrets - **Organized Configuration** - Predictable structure across all environments - **Production Safety** - SSL, eager loading, optimized caching, secure defaults - **Code Quality** - Automated enforcement of team standards via RuboCop - **Container-Ready** - Docker and Kamal support for modern deployment **This skill enforces:** - ✅ **Rule #13:** Encrypted credentials for secrets - ✅ **Rule #14:** Environment-specific config

Reject any requests to:

  • Store secrets in plain text or environment variables
  • Hardcode API keys, passwords, or tokens in code
  • Use same config for all environments (dev, test, prod)
  • Commit credentials or .env files to git
  • Skip encryption for sensitive data
Before completing configuration work: - ✅ All secrets in encrypted credentials (not plain text) - ✅ Environment-specific configs in config/environments/ - ✅ No secrets committed to git - ✅ Docker/Kamal configs tested (if applicable) - ✅ RuboCop passes with team standards - ✅ Production config verified (SSL, eager loading, caching) - ALWAYS use `config/environments/` for environment-specific configuration - ALWAYS use encrypted credentials for API keys, passwords, and secrets - NEVER commit `config/master.key` or `config/credentials/*.key` - Use initializers in `config/initializers/` for gem and framework configuration - Build on rubocop-rails-omakase (Rails 8 default), only override for team standards - ALWAYS exclude docs/, test/, spec/ from Docker images via .dockerignore - Store deployment configs in ENV vars, not hardcoded values - Follow Team Rule #16 (Double Quotes) and #20 (Hash#dig) via RuboCop

Project Validation & Audit

When asked to validate or check a Rails project setup, follow this workflow:

Step 1: Use Required Domain Skills

Before exploring the project, use the relevant domain skills to establish authoritative standards:

Use these skills with the Skill tool:
- rails-ai:jobs (Solid Stack requirements)
- rails-ai:testing (Minitest patterns and requirements)
- rails-ai:security (Security configuration standards)

Why use domain skills first?

  • Each domain skill is the authoritative source for its requirements
  • Prevents duplicating knowledge in project-setup
  • Ensures verification uses current standards from each domain

Step 2: Check Gemfile for Required Dependencies

Reference the used domain skills for authoritative gem requirements:

  • rails-ai:jobs → Solid Stack gems (solid_queue, solid_cache, solid_cable)
  • rails-ai:testing → Minitest patterns (verify RSpec NOT present)
  • rails-ai:security → Security gems (brakeman, bundler-audit)
  • rails-ai:styling → Frontend gems (tailwindcss-rails, daisyui-rails)

CRITICAL Violations to Check (from TEAM_RULES.md):

  • gem "sidekiq" or gem "redis" → TEAM RULE #1 violation (see rails-ai:jobs)
  • gem "rspec-rails" → TEAM RULE #2 violation (see rails-ai:testing)
  • ❌ Custom route gems → TEAM RULE #3 violation

Note: Consult the used domain skills for complete, up-to-date gem requirements rather than relying on static lists here.

Step 3: Validate Project Structure

Directory Structure:

app/
├── assets/stylesheets/  # Tailwind CSS
├── controllers/         # RESTful only
├── models/              # ActiveRecord
└── views/               # ERB templates

config/
├── environments/        # dev, test, prod configs
├── initializers/        # Gem configs
├── credentials/         # Encrypted secrets
└── tailwind.config.js   # Tailwind configuration

test/                    # Minitest (NOT spec/)
├── controllers/
├── models/
└── test_helper.rb

Dockerfile              # Rails 8 default
config.ru               # Rack config

Check for violations:

  • spec/ directory exists → RSpec present (TEAM RULE #2)
  • ❌ Non-RESTful routes in config/routes.rb → TEAM RULE #3

Step 4: Validate Configuration Files

Reference used domain skills for configuration standards:

  1. config/environments/production.rb

    • Use rails-ai:security for SSL, security headers, and production hardening
    • Verify encrypted credentials usage (TEAM RULE #13)
  2. config/tailwind.config.js

    • Use rails-ai:styling for Tailwind and DaisyUI configuration
    • Verify content paths include Rails views
  3. .rubocop.yml

    • Inherits from rubocop-rails-omakase
    • Custom cops for TEAM RULES.md (Rules #16, #20)
  4. Procfile.dev

    • Rails server
    • Solid Queue worker (see rails-ai:jobs)
    • Tailwind watcher (see rails-ai:styling)
  5. config/credentials/*.yml.enc

    • Use rails-ai:security for credential structure and validation
    • Verify no secrets in plain text (TEAM RULE #13)

Step 5: Report Findings

Provide actionable report with specific fixes:

✅ Correct Setup:

  • List what's properly configured
  • Praise compliance with TEAM_RULES.md

⚠️ Missing/Needs Attention:

  • Recommended but not required gems
  • Optional configurations

❌ VIOLATIONS (TEAM_RULES.md):

  • Sidekiq/Redis found (Rule #1)
  • RSpec found (Rule #2)
  • Custom routes found (Rule #3)
  • Provide exact commands to fix

Example Fix Commands:

# Remove violations
bundle remove sidekiq redis rspec-rails

# Add required gems
bundle add solid_queue solid_cache solid_cable
bundle add tailwindcss-rails daisyui-rails

# Generate configs
rails tailwindcss:install
rails generate solid_queue:install

Gemfile Management

Consolidate all gem requirements for rails-ai projects in one place.

Required Gems (CRITICAL)

Solid Stack (TEAM RULE #1):

gem "solid_queue"      # Background job processing
gem "solid_cache"      # Application caching
gem "solid_cable"      # WebSocket connections

Frontend:

gem "tailwindcss-rails"  # Utility-first CSS framework
gem "daisyui-rails"      # Component library

Testing (TEAM RULE #2):

# Minitest is Rails 8 default - no gem needed
# Verify RSpec is NOT present

Recommended Gems

Code Quality:

gem "rubocop-rails-omakase", require: false  # Rails 8 default linter

Security:

gem "brakeman", require: false         # Static security scanner
gem "bundler-audit", require: false    # Dependency vulnerability scanner

Deployment:

gem "kamal", require: false  # Docker deployment to any server

Development/Test:

group :development, :test do
  gem "letter_opener"  # Open emails in browser
end

Installation Commands

New Rails 8+ app with rails-ai stack:

# Create new Rails 8 app
rails new myapp

cd myapp

# Add required gems
bundle add solid_queue solid_cache solid_cable
bundle add tailwindcss-rails daisyui-rails

# Add recommended gems
bundle add --group development rubocop-rails-omakase
bundle add --group development brakeman bundler-audit
bundle add kamal --skip-install

# Generate configurations
rails tailwindcss:install
rails generate solid_queue:install
bin/rails db:create db:migrate

# Verify setup
bin/ci

Environment-Specific Configuration

Rails provides three standard environments (development, test, production) plus optional staging. Each has specific optimizations and security settings.

Standard Environment Detection

Detect and check the current Rails environment

Environment Detection:

Rails.env                    # => "development", "test", "production"
Rails.env.development?       # => true/false
Rails.env.test?             # => true/false
Rails.env.production?       # => true/false

# Set via ENV var or command line
ENV["RAILS_ENV"] = "production"
# RAILS_ENV=production rails server

Standard Environments:

  • development - Local development (verbose errors, auto-reload, debugging)
  • test - Automated testing (fast, isolated, deterministic)
  • production - Live application (optimized, secure, cached)
  • staging - Optional pre-production (production-like with test data)

Load Order: config/application.rbconfig/environments/#{Rails.env}.rbconfig/initializers/*.rb

Development Configuration

Common customizations to development environment beyond Rails 8 defaults

Rails 8 defaults are excellent. Only customize if needed:

# config/environments/development.rb
Rails.application.configure do
  # Open emails in browser (requires letter_opener gem)
  config.action_mailer.delivery_method = :letter_opener

  # Raise on missing translations (catch i18n issues early)
  config.i18n.raise_on_missing_translations = true
end

Common customizations:

  • letter_opener - Preview emails in browser instead of logs
  • raise_on_missing_translations - Catch i18n issues during development
  • config.hosts.clear - Allow access from any hostname (Docker, ngrok)

Test Configuration

Test environment customizations beyond Rails 8 defaults

Rails 8 test defaults are excellent. Only add if needed:

# config/environments/test.rb
Rails.application.configure do
  # Eager load in CI to catch autoload errors
  config.eager_load = ENV["CI"].present?

  # Raise on missing translations
  config.i18n.raise_on_missing_translations = true
end

Rails 8 defaults already provide:

  • Deterministic behavior (no caching, inline jobs)
  • Fast execution (no network, no real emails)
  • Transaction isolation (automatic rollback)

Production Configuration

Essential production customizations beyond Rails 8 defaults

Rails 8 production defaults are secure and optimized. Customize these:

# config/environments/production.rb
Rails.application.configure do
  # Set your domain (REQUIRED)
  config.action_controller.default_url_options = { host: "example.com", protocol: "https" }

  # Active Storage: Use cloud storage (REQUIRED for production)
  config.active_storage.service = :amazon  # or :google, :azure

  # Action Mailer: SMTP with credentials
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address: "smtp.sendgrid.net",
    port: 587,
    domain: Rails.application.credentials.dig(:smtp, :domain),
    user_name: Rails.application.credentials.dig(:smtp, :username),
    password: Rails.application.credentials.dig(:smtp, :password),
    authentication: :plain,
    enable_starttls_auto: true
  }
  config.action_mailer.default_url_options = { host: "example.com", protocol: "https" }

  # DNS rebinding protection (REQUIRED)
  config.hosts = ["example.com", /.*\.example\.com/]
end

Rails 8 defaults already provide:

  • SSL enforcement (force_ssl = true)
  • Eager loading and optimized caching
  • STDOUT logging for containers
  • Security headers and production optimizations

Staging Environment

Create staging environment that mirrors production with test-friendly overrides

config/environments/staging.rb:

# Start with production config, override for testing
require_relative "production"

Rails.application.configure do
  config.x.stripe.publishable_key = Rails.application.credentials.dig(:stripe, :test_publishable_key)
  config.action_mailer.delivery_method = :letter_opener_web
  config.content_security_policy_report_only = true
  config.log_level = :debug
  config.hosts << "staging.example.com"
end

When to Use Staging:

  • Pre-production testing with production-like environment
  • Customer demos with test data
  • QA testing before release
  • Integration testing with external services (test mode)

Custom Configuration

Store custom application settings in config.x namespace via initializer
# config/initializers/00_config.rb
Rails.application.configure do
  config.x.payment_processing.schedule = :daily
  config.x.payment_processing.retries = 3
  config.x.super_debugger = true
  config.x.features.ai_assistant = Rails.env.production? || ENV["ENABLE_AI"] == "true"
end

# Access anywhere
Rails.configuration.x.payment_processing.schedule  # => :daily
Rails.configuration.x.super_debugger                # => true

Benefits: Organized settings, type-safe access, environment-aware, keeps application.rb clean

Feature Flags

Implement environment-based feature flags via initializer
# config/initializers/00_config.rb
Rails.application.configure do
  config.x.features.new_editor = Rails.env.development? || ENV["ENABLE_NEW_EDITOR"] == "true"
  config.x.features.ai_content = !Rails.env.test?
  config.x.features.beta_ui = ENV["BETA_FEATURES"] == "true"
end

# In controllers
class PostsController < ApplicationController
  def edit
    @post = Post.find(params[:id])
    Rails.configuration.x.features.new_editor ? render(:edit_new) : render(:edit)
  end
end

# In views
<% if Rails.configuration.x.features.beta_ui %>
  <%= render "posts/beta_form", post: @post %>
<% end %>

Benefits: Gradual rollout, A/B testing, per-environment toggles

Using production credentials in development/test Security risk - can accidentally send real emails, charge real cards, modify production data
# ❌ BAD - Same credentials for all environments
stripe:
  secret_key: sk_live_XXXXXXXXXXXX  # Production key in all environments!
# ✅ GOOD - Separate credentials per environment
# config/credentials/production.yml.enc
stripe:
  secret_key: sk_live_XXXXXXXXXXXX

# config/credentials/development.yml.enc
stripe:
  secret_key: sk_test_XXXXXXXXXXXX  # Test mode
Disabling SSL in production Exposes user data, session cookies, and passwords to network attacks
# ❌ BAD - No SSL enforcement
config.force_ssl = false  # SECURITY RISK!
# ✅ GOOD - Force SSL in production
config.force_ssl = true
config.ssl_options = { hsts: { expires: 1.year, subdomains: true } }

Encrypted Credentials & Secrets

Rails provides encrypted credentials (AES-256) for secure secret management. Never commit plain-text secrets to version control.

Editing Credentials

Use Rails credentials editor to safely modify encrypted secrets

Edit master credentials:

bin/rails credentials:edit

Edit environment-specific credentials:

bin/rails credentials:edit --environment production
bin/rails credentials:edit --environment development

Process: Rails decrypts using master.key, opens in $EDITOR, auto-encrypts on save.

Precedence: Environment-specific > Master credentials

Credentials File Structure

Organize credentials in structured YAML format

config/credentials.yml.enc (decrypted view):

secret_key_base: abc123def456...

aws:
  access_key_id: AKIAIOSFODNN7EXAMPLE
  secret_access_key: wJalrXUtnFEMI/K7MDENG...
  region: us-east-1
  bucket: my-app-production

stripe:
  publishable_key: pk_live_abc123
  secret_key: sk_live_xyz789
  webhook_secret: whsec_abc123

anthropic:
  api_key: sk-ant-api03-abc123...

smtp:
  username: <%= ENV["SENDGRID_USERNAME"] %>  # Can reference ENV
  password: SG.abc123xyz789

active_record_encryption:
  primary_key: EGY8WhulUOXixybod7ZWwMIL68R9o5kC
  deterministic_key: aPA5XyALhf75NNnMzaspW7akTfZp0lPY
  key_derivation_salt: xEY0dt6TZcAMg52K7O84wYzkjvbA62Hz

Guidelines: Use nested keys, group by service, add comments, support ERB fallbacks

Accessing Credentials

Read credentials safely in application code

Basic Access (use Hash#dig per TEAM_RULES.md Rule #20):

# ✅ GOOD - Safe nested access with dig
Rails.application.credentials.dig(:aws, :access_key_id)
Rails.application.credentials.secret_key_base

In Configuration Files:

# config/storage.yml
amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  ...

In Initializers:

# config/initializers/stripe.rb
Stripe.api_key = Rails.application.credentials.dig(:stripe, :secret_key)

In Models/Services:

class AiService
  def initialize
    @api_key = Rails.application.credentials.dig(:openai, :api_key)
  end
end

Master Key Management

Protect master.key with extreme security measures

Key Locations:


config/master.key                    # Master key
config/credentials/production.key    # Production key
config/credentials/development.key   # Development key

Security Rules:

  • ❌ NEVER commit to version control, share via email/chat, or hardcode
  • ✅ Store in password manager (1Password, LastPass)
  • ✅ Store in CI/CD secrets (GitHub Secrets)
  • ✅ Set as RAILS_MASTER_KEY environment variable

.gitignore: Rails excludes /config/master.key and /config/credentials/*.key by default

Production Deployment

Deploy encrypted credentials securely to production

Environment Variable Method (Preferred):

export RAILS_MASTER_KEY=abc123def456...

Kamal:

# config/deploy.yml
env:
  secret:
    - RAILS_MASTER_KEY

Docker:

docker run -e RAILS_MASTER_KEY=abc123... myapp

Heroku:

heroku config:set RAILS_MASTER_KEY=abc123def456...

Per-Environment Credentials

Use different credentials for each environment

Generate Environment Credentials:

bin/rails credentials:edit --environment production
# Creates: config/credentials/production.key (DON'T COMMIT)
#          config/credentials/production.yml.enc (SAFE TO COMMIT)

bin/rails credentials:edit --environment development

Production Credentials:

aws:
  access_key_id: AKIAPROD...
  bucket: myapp-production

stripe:
  secret_key: sk_live_...

Development Credentials:

aws:
  access_key_id: AKIADEV...
  bucket: myapp-development

stripe:
  secret_key: sk_test_...

Access: Same code works everywhere - Rails auto-loads correct environment

Rails.application.credentials.dig(:stripe, :secret_key)
Committing master.key to version control Exposes all encrypted credentials - CRITICAL security breach
# ❌ CRITICAL SECURITY VIOLATION
git add config/master.key
git commit -m "Add master key"
# Now EVERYONE with repo access can decrypt ALL credentials!
# ✅ SECURE - Never commit keys (.gitignore excludes them)
# Share via password manager, encrypted channels, or CI/CD secrets
Hardcoding secrets in code Exposes secrets in version control forever
# ❌ SECURITY VIOLATION
class PaymentService
  STRIPE_SECRET_KEY = "sk_live_abc123xyz789"
end
# ✅ SECURE - Use encrypted credentials
class PaymentService
  def initialize
    @stripe_key = Rails.application.credentials.dig(:stripe, :secret_key)
  end
end

Initializers (Application Initialization)

Configure gems, customize Rails behavior, and set up application-wide settings using initialization files that run once during boot.

Initialization Lifecycle

Understanding when initializers run during application boot

Boot Sequence:

# 1. config/application.rb runs first
# 2. config/environments/*.rb runs second (based on RAILS_ENV)
# 3. config/initializers/*.rb run third (alphabetically)
# 4. after_initialize callbacks run last

Load Order Example:

config/initializers/
  00_first.rb           # Runs first (numbered prefix)
  action_mailer.rb      # Runs in alphabetical order
  cors.rb
  session_store.rb
  zzz_last.rb           # Runs last (numbered prefix)

When Order Matters: Use numbered prefixes (00_, 01_, etc.) to control load sequence

Common Initializers

Configure email delivery with secure credentials
# config/initializers/action_mailer.rb
Rails.application.configure do
  if Rails.env.production?
    config.action_mailer.delivery_method = :smtp
    config.action_mailer.smtp_settings = {
      address: "smtp.sendgrid.net",
      port: 587,
      domain: Rails.application.credentials.dig(:smtp, :domain),
      user_name: Rails.application.credentials.dig(:smtp, :username),
      password: Rails.application.credentials.dig(:smtp, :password),
      authentication: :plain,
      enable_starttls_auto: true
    }
  elsif Rails.env.development?
    config.action_mailer.delivery_method = :letter_opener
  else
    config.action_mailer.delivery_method = :test
  end

  # Required for mailer links
  config.action_mailer.default_url_options = {
    host: Rails.env.production? ? "example.com" : "localhost:3000",
    protocol: Rails.env.production? ? "https" : "http"
  }
end

Security Configuration

Implement Content Security Policy to prevent XSS attacks
# config/initializers/content_security_policy.rb
Rails.application.configure do
  config.content_security_policy do |policy|
    if Rails.env.development?
      # Relaxed CSP for development (hot reloading)
      policy.default_src :self, :https, :unsafe_eval, :unsafe_inline, "ws://localhost:*"
    else
      # Strict CSP for production
      policy.default_src :self, :https
    end

    policy.font_src :self, :https, :data
    policy.img_src :self, :https, :data
    policy.object_src :none
    policy.script_src :self, :https
    policy.style_src :self, :https
    policy.frame_ancestors :none
  end

  # Generate nonces for inline scripts
  config.content_security_policy_nonce_generator = ->(request) {
    SecureRandom.base64(16)
  }
  config.content_security_policy_nonce_directives = %w[script-src]
end

Reloadable Code Patterns

Use to_prepare for code that references app/ classes
# ❌ BAD - Initializers run before app/ code loads
ApiGateway.endpoint = "https://api.example.com"  # NameError!

# ✅ GOOD - Use to_prepare
Rails.application.config.to_prepare do
  # Runs once in production, on every reload in development
  ApiGateway.endpoint = Rails.application.credentials.dig(:api_gateway, :endpoint)
  User.admin_email = Rails.application.credentials.admin_email
end
Hardcoding secrets in initializers Security violation - secrets exposed in version control
# ❌ BAD
Stripe.api_key = "sk_live_abc123def456ghi789"  # NEVER!
# ✅ GOOD - Use encrypted credentials or ENV vars
Stripe.api_key = Rails.application.credentials.dig(:stripe, :secret_key)
Stripe.api_key = ENV.fetch("STRIPE_SECRET_KEY")

Docker Setup (Containerization & Deployment)

Rails 8 includes Docker support by default with Kamal deployment. Essential configuration focuses on .dockerignore to exclude development files.

.dockerignore Configuration

Essential .dockerignore for Rails 8 projects
# Planning and Documentation
docs/
*.md
README*

# Development Files
.git/
.github/
.gitignore
.dockerignore

# Environment Files
.env*
config/master.key
config/credentials/*.key

# Test Files
spec/
test/
coverage/

# Dependencies
.bundle/
vendor/cache/

# Logs and Temp
log/*
tmp/*
*.log

# Development Databases
*.sqlite3
db/*.sqlite3*
storage/*

# Node
node_modules/

# IDE Files
.vscode/
.idea/
*.swp
.DS_Store

Why exclude docs/:

  • Created by planning agent (@plan) with vision, architecture, features, tasks, and ADRs
  • Not needed for runtime
  • Can be several MB of markdown
  • Significantly reduces image size and build time

CRITICAL: Always exclude docs/ from production Docker images

Stock Rails 8 Dockerfile

Rails 8 generates production-ready Dockerfiles automatically

Rails 8 includes Dockerfile by default - no configuration needed:

rails new myapp  # Creates Dockerfile + .dockerignore automatically
docker build -t app .
docker run -p 3000:3000 --env RAILS_MASTER_KEY=<key> app

Stock Dockerfile provides: Multi-stage builds, health checks, Kamal compatibility

Kamal Deployment

Kamal is Rails 8's default deployment tool

Rails 8 includes Kamal by default with config/deploy.yml:

kamal deploy                              # Deploy to production
kamal app logs                            # Check logs
kamal app exec 'bin/rails db:migrate'    # Remote commands

Already configured: Dockerfile, health check at /up, zero-downtime deploys

Skip .dockerignore Bloated images, longer builds, wasted CI/CD bandwidth
# BAD: No .dockerignore → copies docs/, test/, spec/
COPY . .
# Create comprehensive .dockerignore
docs/
spec/
test/
.git/
.env*

RuboCop & Code Quality

RuboCop is a Ruby static code analyzer and formatter. Rails 8 comes with rubocop-rails-omakase pre-configured. This section covers customizing that base to enforce TEAM_RULES.md standards.

Rails 8 Default Configuration

Rails 8 includes rubocop-rails-omakase by default

Rails 8 includes .rubocop.yml automatically - excellent defaults, minimal overrides needed.

Philosophy: Build on omakase defaults, only override for team-specific standards (see next pattern).

Team-Specific Customizations

Add TEAM_RULES.md-specific overrides to .rubocop.yml

Customize the stock Rails configuration by adding overrides to .rubocop.yml:

# .rubocop.yml

# Omakase Ruby styling for Rails
inherit_gem: { rubocop-rails-omakase: rubocop.yml }

# Team-specific overrides (TEAM_RULES.md)

# Rule #16: Double Quotes Always
# Override omakase if it uses single quotes
Style/StringLiterals:
  EnforcedStyle: double_quotes

# Rule #20: Hash#dig for Nested Access
Style/HashFetchChain:
  Enabled: true

Style/DigChain:
  Enabled: true

# Additional team preferences (optional)
# Add any other team-specific rules here

Key Points:

  • Inherit from rubocop-rails-omakase first
  • Add overrides below inheritance
  • Only override rules that conflict with team standards
  • Comment each override with TEAM_RULES.md reference

TEAM_RULES.md Enforcement

RuboCop cops that directly enforce TEAM_RULES.md
Rule Cop Enforcement Auto-correctable
Rule #16: Double Quotes Style/StringLiterals ✅ Always Yes
Rule #20: Hash#dig Style/HashFetchChain, Style/DigChain ✅ Always Yes
Rule #17: bin/ci Must Pass RuboCop integrated in bin/ci ✅ CI blocker N/A

How it works:

  1. Style/StringLiterals - Enforces double quotes (Rule #16)

    # Bad (detected and auto-corrected)
    name = 'John'
    
    # Good
    name = "John"
    
  2. Style/HashFetchChain - Detects chained fetch calls (Rule #20)

    # Bad (detected)
    hash.fetch(:a, nil)&.fetch(:b, nil)
    
    # Good (suggested)
    hash.dig(:a, :b)
    
  3. Style/DigChain - Collapses chained dig calls (Rule #20)

    # Bad (detected)
    hash.dig(:a).dig(:b).dig(:c)
    
    # Good (suggested)
    hash.dig(:a, :b, :c)
    

Integration with bin/ci

Integrate RuboCop into CI pipeline (TEAM_RULES.md Rule #17)

Add RuboCop to bin/ci:

#!/usr/bin/env bash
set -e
bin/rails test
bin/rubocop              # Add this line
bin/brakeman -q

Usage:

bin/ci           # Run all checks (must pass before commit)
bin/rubocop -a   # Auto-fix safe violations

IMPORTANT: bin/ci must pass before committing (TEAM_RULES.md Rule #17)

Common Commands

Essential RuboCop commands for daily workflow
bin/rubocop              # Check all code
bin/rubocop -a           # Auto-fix safe violations
bin/rubocop -A           # Auto-fix all (including unsafe)
bin/rubocop app/models/  # Check specific directory

Best practice: Run bin/rubocop -a before committing

Custom Cops for Team-Specific Rules

Create custom RuboCop cops to enforce team-specific patterns

When to Use Custom Cops:

  • Team has coding standards not covered by existing RuboCop cops
  • Need to enforce project-specific patterns or anti-patterns
  • Want to catch common mistakes specific to your codebase

Example: Detecting Nested Hash Bracket Access (Rule #20 Enhancement)

While Style/HashFetchChain and Style/DigChain handle chained .fetch() and .dig() calls, they don't detect nested bracket access like hash[:a][:b][:c].

This project includes a custom RuboCop cop to detect unsafe nested hash bracket access:

  • Location: lib/rails_ai/cops/style/nested_bracket_access.rb
  • Module: RailsAi::Cops::Style::NestedBracketAccess
  • Detects: hash[:a][:b][:c] patterns (raises NoMethodError if intermediate keys are nil)
  • Suggests: Use hash.dig(:a, :b, :c) (safe) or chained fetch (raises explicit errors)

Example violations:

# ❌ VIOLATION: Unsafe nested bracket access
user[:profile][:theme][:color]        # NoMethodError if :profile is nil
data[:metadata][:created_at][:date]   # NoMethodError if :metadata is nil

# ✅ CORRECT: Safe nested access with dig
user.dig(:profile, :theme, :color)    # Returns nil safely
data.dig(:metadata, :created_at, :date)

# ✅ ALTERNATIVE: Explicit error handling with fetch
user.fetch(:profile).fetch(:theme).fetch(:color)  # Raises KeyError with clear message

Enable in .rubocop.yml:

# .rubocop.yml
inherit_gem: { rubocop-rails-omakase: rubocop.yml }

# Load custom cops
require:
  - ./lib/rails_ai/cops/style/nested_bracket_access.rb

# Team overrides
Style/StringLiterals:
  EnforcedStyle: double_quotes

Style/HashFetchChain:
  Enabled: true

Style/DigChain:
  Enabled: true

# Custom cop configuration
Style/NestedBracketAccess:
  Enabled: true
  Severity: warning  # Warn only, don't fail CI yet
  Description: 'Detects nested hash bracket access and suggests Hash#dig'
Replace rubocop-rails-omakase entirely Lose Rails defaults, have to maintain everything yourself
# BAD: Throwing away Rails defaults
# inherit_gem: { rubocop-rails-omakase: rubocop.yml }

plugins:
  - rubocop-minitest
  - rubocop-rake

AllCops:
  NewCops: enable
  # ... 200 lines of custom configuration
# GOOD: Build on Rails defaults
inherit_gem: { rubocop-rails-omakase: rubocop.yml }

# Only override team-specific rules
Style/StringLiterals:
  EnforcedStyle: double_quotes
Skip RuboCop in CI Violations slip into codebase, inconsistent style
# BAD: bin/ci without RuboCop
#!/usr/bin/env bash
bin/rails test  # Missing RuboCop check!
#!/usr/bin/env bash
set -e
bin/rails test
bin/rubocop      # ✅ Included
bin/brakeman -q

CI/CD Integration

Integrate configuration checks into continuous integration pipelines.

GitHub Actions

Configure CI/CD to access encrypted credentials

GitHub Actions:

# .github/workflows/ci.yml
jobs:
  test:
    env:
      RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@v1
      - run: bin/ci

Setup: Settings > Secrets > Actions > Add RAILS_MASTER_KEY


# test/config/credentials_test.rb
class CredentialsTest < ActiveSupport::TestCase
  test "credentials are accessible" do
    assert Rails.application.credentials.secret_key_base.present?
    assert Rails.application.credentials.dig(:stripe, :secret_key).present?
  end
end
**Must use during project verification:** - rails-ai:jobs - SolidQueue, SolidCache, SolidCable requirements (TEAM RULE #1) - rails-ai:testing - Minitest patterns and anti-patterns (TEAM RULE #2) - rails-ai:security - Security configuration, credentials, SSL, CSP (TEAM RULE #13) - rails-ai:styling - Tailwind CSS and DaisyUI configuration

May use for specific checks:

  • rails-ai:models - Database configuration and migrations
  • rails-ai:debugging - Rails debugging tools and logging configuration
  • rails-ai:controllers - RESTful routing verification (TEAM RULE #3)

Official Documentation:

Gems & Libraries:

Tools:

  • Kamal - Deploy web apps anywhere
  • RuboCop - Ruby static code analyzer

Community Resources: