# Extraction Timing

Guides decisions about when and how to extract code into services, queries, concerns...

- Repository: https://github.com/ThibautBaissac/rails_ai_agents (671 stars)
- Category: Design
- License: MIT
- Last updated: 2026-06-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add ThibautBaissac/rails_ai_agents --skill extraction-timing -g -a claude-code -y`
Codex: `npx skills add ThibautBaissac/rails_ai_agents --skill extraction-timing -g -a codex -y`
Cursor: `npx skills add ThibautBaissac/rails_ai_agents --skill extraction-timing -g -a cursor -y`
Gemini CLI: `npx skills add ThibautBaissac/rails_ai_agents --skill extraction-timing -g -a gemini-cli -y`

## Description

Guides decisions about when and how to extract code into services, queries, concerns, form objects, or other patterns. Use when deciding whether to extract code, choosing between patterns (service vs concern vs query), evaluating if a base class or abstraction is needed, or when user mentions refactoring, extraction, code organization, or "where should this go." WHEN NOT: Implementing a specific pattern already decided on (use specialist agents like service-agent, query-agent, or model-agent), writing tests (use rspec-agent), or architecture-level design (use rails-architecture).

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

You are an expert in Rails code organization and extraction decisions. Help decide **when** to extract, **what pattern** to use, and **when to keep it simple**.

## Core Philosophy: Skinny Everything

The 2025 Rails consensus has evolved beyond "Fat Models" to **Skinny Everything**:
- **Controllers**: orchestrate (delegate to services, render responses) -- max ~10 lines per action
- **Models**: persist (validations, associations, scopes, simple predicates) -- max ~100 lines
- **Services**: contain business logic (multi-step operations, external calls, orchestration)
- **Views**: display markup with zero logic

## Extraction Thresholds

| Signal | Action |
|--------|--------|
| Controller action exceeds ~10 lines of business logic | Extract to service object |
| Model exceeds ~100 lines | Extract business logic to services, complex queries to query objects |
| Query joins multiple tables or has conditional clauses | Extract to query object |
| Form touches multiple models or has custom validation | Extract to form object |
| Display formatting logic in model | Extract to presenter |
| UI element reused across 2+ views | Extract to ViewComponent |
| Shared behavior across 2+ models (narrow, simple) | Extract to concern |
| 5+ concrete implementations with identical structure | Extract base class |
| One-off operation | **Don't extract. Inline is fine.** |

## Decision Tree: "Where Should This Code Go?"

```
Is it a database query?
  ├── Simple (one table, one condition) → Model scope
  └── Complex (joins, conditionals, reused) → Query object

Is it business logic?
  ├── Simple CRUD on one model → Controller inline (or model method)
  ├── Multi-step operation → Service object
  ├── Involves external API → Service object
  └── Spans multiple models → Service object with transaction

Is it shared behavior?
  ├── Property of the model (soft-delete, slugs, search) → Concern
  └── Operation on the model (checkout, import, sync) → Service object

The rest: https://github.com/ThibautBaissac/rails_ai_agents/blob/HEAD/.agents/skills/extraction-timing/SKILL.md
