CtrlK
BlogDocsLog inGet started
Tessl Logo

igmarin/rails-agent-skills

Curated library of 39 AI agent skills for Ruby on Rails development. Organized by category: planning, testing, code-quality, ddd, engines, infrastructure, api, patterns, context, orchestration, and workflows. Includes 5 callable workflow skills (rails-tdd-loop, rails-review-flow, rails-setup-flow, rails-quality-flow, rails-engines-flow) for complete development cycles. Covers code review, architecture, security, testing (RSpec), engines, service objects, DDD patterns, and TDD automation.

95

1.20x
Quality

98%

Does it follow best practices?

Impact

95%

1.20x

Average score across 35 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

SKILL.mdskills/code-quality/rails-code-conventions/

name:
rails-code-conventions
license:
MIT
description:
A daily checklist for writing clean Rails code, covering design principles (DRY, YAGNI, PORO, CoC, KISS), per-path rules (models, services, workers, controllers), structured logging, and comment discipline. Defers style and formatting to the project's configured linter(s). Use when writing, reviewing, or refactoring Ruby on Rails code, or when asked about Rails best practices, clean code, or code quality. Trigger words: code review, refactor, RoR, clean code, best practices, Ruby on Rails conventions.

Rails Code Conventions

Style source of truth: Style and formatting defer to the project's configured linter(s). This skill adds non-style behavior and architecture guidance only. For Hotwire + Tailwind specifics, see rails-stack-conventions.

Linter — initial analysis

Detect → run → defer. Do not invent style rules.

  • Ruby: check for .rubocop.yml / standard gem → bundle exec rubocop or bundle exec standardrb
  • Frontend: check for eslint.config.*, .eslintrc*, biome.json, or package.json lint script → run accordingly
  • If no config is found: note this to the user — do not default to any tool.

Quick Reference

TopicRule
Style/formatProject linter(s) — detect and run as above; do not invent style rules here
PrinciplesDRY, YAGNI, PORO where it helps, CoC, KISS
Comments / tagsExplain why; tagged notes need actionable context
LoggingFirst arg: static string; second arg: hash with event: key; no interpolation; backtrace on errors
Deep stacksChain rails-stack-conventions → domain skills (services, jobs, RSpec)

Code Review / Refactoring Workflow

When reviewing or refactoring Rails code, follow this sequence:

  1. Run linter — detect config, run the appropriate tool, note absence if none found.
  2. Check area-specific rules — apply the "Apply by area" table below to each changed path.
  3. Verify tests gate — confirm failing tests exist before any new behavior; run specs and checkpoints.
  4. Chain to specialised skills — use the Integration table to pull in deeper guidance (security, jobs, specs, etc.) as needed.

Comments and tagged notes

Comment why, not what. Tagged notes — TODO: / FIXME: / HACK: / NOTE: / OPTIMIZE: — are MANDATORY in these triggers; every tag carries actionable context (owner, ticket id, deadline, or next step). Naked tags (# TODO: fix this) fail review.

TriggerRequired tag
Business-rule constant (rates, caps, thresholds)NOTE: with the rule's source/owner
Deferred work / known shortcutTODO: with ticket or next step
Workaround for a bug or external limitationHACK: or FIXME: with the upstream issue
Performance tradeoff or hot pathOPTIMIZE: with the measured concern
# BAD — naked tag, no context
# TODO: fix this
rate = TIER_RATES.fetch(tier, 0.0)

# GOOD
# NOTE: 50% cap set by Pricing policy v3 (PRI-118, owner: pricing-team).
MAX_DISCOUNT = 0.50

# GOOD — TODO with next step + dependency
# TODO: replace TIER_RATES with DB-backed lookup (PRI-482; blocked on legal).
rate = TIER_RATES.fetch(tier, 0.0)

Structured Logging

MANDATORY SHAPE — every Rails.logger.* call uses exactly two positional arguments.

Rails.logger.<level>(static_string_message, { event: "dot.namespaced", ...domain_fields })
#                    └── 1st arg: STRING ──┘  └─────────── 2nd arg: HASH ───────────┘
  • 1st arg (string): a static string literal — no interpolation, no variables. Log aggregators group on this dimension.
  • 2nd arg (hash): first key is always event: with a dot-namespaced value (do NOT use :type, :action, or :name). All dynamic data goes here.
  • Errors: every rescue logs both e.message and e.backtrace.first(5).join("\n") as hash fields — backtrace is non-optional.
# BAD — interpolation destroys log aggregator grouping; single-arg call loses structured fields
Rails.logger.info("Processing order #{order.id}")
Rails.logger.info(event: "order.processing_started", order_id: order.id)

# GOOD
Rails.logger.info("order.processing_started", {
  event: "order.processing_started",
  order_id: order.id,
  user_id: user.id
})

# GOOD — error path with backtrace
rescue StandardError => e
  Rails.logger.error("order.processing_failed", {
    event: "order.processing_failed",
    order_id: order.id,
    error: e.message,
    backtrace: e.backtrace.first(5).join("\n")
  })
  raise
end

Apply by area (path patterns)

Rules below apply when those paths exist in the project. If a path is absent, skip that row.

AreaPath patternGuidance
ActiveRecord performanceapp/models/**/*.rbEager load in loops; prefer pluck / exists? / find_each. N+1: run bullet → fix eager loads → re-run clean
Background jobsapp/workers/**/*.rb, app/jobs/**/*.rbDepth: rails-background-jobs
Error handlingapp/services/**/*.rb, app/lib/**/*.rb, app/exceptions/**/*.rbDomain exceptions + layer rescue_from; specs must cover rescue paths
Logging / tracingapp/services/**/*.rb, app/workers/**/*.rb, app/jobs/**/*.rb, app/controllers/**/*.rb, app/repositories/**/*.rbStructured logs (see above); APM spans/tags on hot paths when stack has APM
Controllersapp/controllers/**/*_controller.rbStrong params; thin actions → services; IDOR / PII → rails-security-review
Repositoriesapp/repositories/**/*.rbNew repos only for SQL, caching, clear boundary, or external I/O — document why
RSpecspec/**/*_spec.rbFactoryBot; request over controller specs; env: (or project pattern) for ENV; let > let! unless eager setup required; avoid heavy before when let is clearer
Serializersapp/serializers/**/*.rbExplicit keys; no N+1; preload associations passed in
Service objectsapp/services/**/*.rbSingle responsibility; .call / injected deps per ruby-service-objects; after extract, specs + caller still green
SQL securityRaw SQL anywhereBind params / sanitize_sql_array; whitelist dynamic ORDER BY; document why raw SQL

RSpec and let_it_be (test-prof)

Only recommend let_it_be if test-prof is already in Gemfile.lock. Otherwise default to let; reach for let! only when lazy evaluation would break the example. Don't introduce test-prof unless asked.

HARD-GATE: Tests Gate Implementation

When this skill guides new behavior, the tests gate still applies:

PRD → TASKS → TEST (write, run, fail) → IMPLEMENTATION → …

No implementation code before a failing test. See rspec-best-practices and rails-agent-skills.

Output Style

Every Rails-code task lands these:

  1. Comments follow the Comments and tagged notes section: no what-comments; tagged notes (TODO: / FIXME: / HACK: / NOTE: / OPTIMIZE:) on every assumption, deferred work, or business-rule constant; every tag carries actionable context (owner, ticket id, deadline).
  2. Logging follows Structured Logging above — static first arg, hash second arg with event:, and a backtrace line on every error rescue.
  3. Linter detection noted — when reviewing or refactoring, state which linter config you detected (or its absence) before any style claim.

Integration

SkillWhen to chain
rails-stack-conventionsStack-specific: PostgreSQL, Hotwire, Tailwind
ddd-rails-modelingWhen domain concepts and invariants need clearer Rails-first modeling choices
ruby-service-objectsImplementing or refining service objects
rails-background-jobsWorkers, queues, retries, idempotency
rspec-best-practicesSpec style, tests gate (red/green/refactor), request vs controller specs
rails-security-reviewControllers, params, IDOR, PII
rails-code-reviewFull PR pass before merge

Assets

  • assets/checklist.md
  • assets/snippets.md

skills

code-quality

rails-code-conventions

README.md

tile.json