Rails_ai_agents extraction-timing
install
source · Clone the upstream repo
git clone https://github.com/ThibautBaissac/rails_ai_agents
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ThibautBaissac/rails_ai_agents "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/extraction-timing" ~/.claude/skills/thibautbaissac-rails-ai-agents-extraction-timing && rm -rf "$T"
manifest:
.claude/skills/extraction-timing/SKILL.mdsource content
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 Is it display logic? ├── Formatting one model's data → Presenter (SimpleDelegator) ├── Reusable UI element → ViewComponent └── Simple helper method → Keep in helper (use sparingly) Is it validation? ├── Single model, standard rules → Model validation ├── Multi-model form → Form object └── Business rule (not data integrity) → Service validation
Settled Debates
Concerns vs Service Objects
| Concerns | Service Objects | |
|---|---|---|
| Use for | Simple shared model properties | Multi-step business operations |
| Examples | , , | , , |
| Max size | ~30 lines | No hard limit (but SRP applies) |
| Test via | Including model's specs | Isolated unit specs |
Rule: If the behavior is a property of the model, use a concern. If it's an operation on the model, use a service.
STI vs Polymorphic Associations
| STI | Polymorphic | |
|---|---|---|
| Use when | Subclasses share >80% of columns | Types have unique attributes |
| Table | One shared table with column | Separate tables per type |
| Avoid when | >20% columns are NULL for some subtypes | Types are fundamentally similar |
Callbacks vs Explicit Calls
Rule: Callbacks for data normalization only. Everything else is explicit.
| Acceptable Callbacks | Must Be Explicit (in services) |
|---|---|
| Sending emails |
| Enqueuing background jobs |
| Calling external APIs |
| Creating related records with business logic |
Anti-Pattern Checklist
Before extracting, verify you're not creating:
- A service that wraps a single
call (Service Graveyard)model.update! - A base class for only 2 services (Premature Abstraction)
- A concern with multiple responsibilities (Kitchen Sink Concern)
- A helper that should be a presenter or component
- An abstraction for a hypothetical future need (YAGNI violation)
Reference
See @docs/rails-development-principles.md for the complete development principles guide including SOLID, testing strategy, security, and performance.