Layered Rails
Design and review Rails applications using layered architecture principles.
Quick Start
Rails applications are organized into four architecture layers with unidirectional data flow:
┌─────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ Controllers, Views, Channels, Jobs* │
│ Forms, Filters, Presenters, Serializers │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ APPLICATION LAYER │
│ Services, Policies, Mailers, Deliveries │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ DOMAIN LAYER │
│ Models, Value Objects, Query Objects │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ INFRASTRUCTURE LAYER │
│ Active Record, API Clients, Storage │
└─────────────────────────────────────────┘
* Jobs are internal inbound entry points: design-wise they follow the same rules as controllers, minus authentication and user-input handling.
Core Rule: Lower layers must never depend on higher layers.
See Architecture Layers Reference for the full layer responsibilities and the Four Rules deep-dive.
What this skill is for
Use this skill when:
- Analyzing a codebase — apply the architecture analysis for a full audit, or zoom in with the service-layer audit, callback analysis, or god-object analysis.
- Reviewing code changes — run the code review workflow on a diff, file, or branch.
- Running the specification test — use the spec-test workflow on a single file or directory to evaluate whether code belongs in its current layer.
- Planning gradual adoption — generate a phased roadmap with the layerification plan workflow, focused on a goal like "introduce authorization" or "decompose god objects."
- Planning a feature — I'll apply the layered principles below to whichever code you're about to write.
- Implementing a specific pattern — authorization, notifications, view components, AI integration, etc. — see the Pattern Catalog and Topic References below.
In Claude Code with this skill installed as a plugin (/plugin install layered-rails@layered-rails-skills), each workflow above is also reachable as a slash command — see Slash Commands. Natural-language requests ("review this file with layered-rails", "run the specification test on app/models/order.rb") work in any environment that has the skill loaded.
Workflows
Reusable procedures bundled inside this skill. Read the file and apply it to the target code:
- Architecture analysis — full layered-architecture audit of a Rails codebase
- Code review — review a diff or file set for layer violations
- Specification test — evaluate whether code belongs in its current layer
- Service-layer audit — deep audit of
app/services/ and service-like classes (per-cluster proposals, contracts, layer hygiene)
- Callback analysis — score Active Record callbacks and find extraction candidates
- God-object analysis — identify oversized models and recommend decomposition
- Gradual layerification plan — incremental roadmap for adopting layered patterns
- ArchSpec setup — generate and verify a tailored
Archspec.rb enforcing the layer boundaries in CI
Core Principles
The Four Rules
- Unidirectional Data Flow - Data flows top-to-bottom only
- No Reverse Dependencies - Lower layers never depend on higher layers
- Abstraction Boundaries - Each abstraction belongs to exactly one layer
- Minimize Connections - Fewer inter-layer connections = looser coupling
Common Violations
| Violation |
Example |
Fix |
| Model uses Current |
Current.user in model |
Pass user as explicit parameter |
| Service accepts request |
param :request in service |
Extract value object from request |
| Controller has business logic |
Pricing calculations in action |
Extract to service or model |
| Anemic models |
All logic in services |
Keep domain logic in models |
| Category |
Reference |
| Layer violations (Current in models, request in services, notifications in models, business logic in controllers) |
layer-violations.md |
| Service objects (anemic models, bag of random objects, premature abstraction) |
service-objects.md |
| Callbacks (operation callbacks, skip callbacks, control flags) |
callbacks.md |
| Concerns (code-slicing, overgrown) |
concerns.md |
| Helpers (HTML construction in helpers) |
helpers.md |
| Jobs (anemic jobs) |
jobs.md |
| Testing (testing wrong layer) |
testing.md |
The Specification Test
If the specification of an object describes features beyond the primary responsibility of its abstraction layer, such features should be extracted into lower layers.
How to apply:
- List responsibilities the code handles
- Evaluate each against the layer's primary concern
- Extract misplaced responsibilities to appropriate layers
See Specification Test Reference for detailed guide.
Pattern Catalog
| Pattern |
Layer |
Use When |
Reference |
| Service Object |
Application |
Orchestrating domain operations |
service-objects.md |
| Query Object |
Domain |
Complex, reusable queries |
query-objects.md |
| Form Object |
Presentation |
Multi-model forms, complex validation |
form-objects.md |
| Filter Object |
Presentation |
Request parameter transformation |
filter-objects.md |
| Presenter |
Presentation |
View-specific logic, multiple models |
presenters.md |
| Serializer |
Presentation |
API response formatting |
serializers.md |
| Policy Object |
Application |
Authorization decisions |
policy-objects.md |
| Value Object |
Domain |
Immutable, identity-less concepts |
value-objects.md |
| Collaborator Object |
Domain |
A slice of one model's behavior in a typed delegate |
collaborator-objects.md |
| State Machine |
Domain |
States, events, transitions |
state-machines.md |
| Concern |
Domain |
Shared behavioral extraction |
concerns.md |
| Repository |
Domain |
Last resort — returning custom domain objects mapped from AR data, after AR scopes (simple) and query objects (query building) are insufficient |
repositories.md |
Pattern Selection Guide
"Where should this code go?"
| If you have... |
Consider... |
| Complex multi-model form |
Form Object |
| Request parameter filtering/transformation |
Filter Object |
| View-specific formatting |
Presenter |
| Complex database query used in multiple places |
Query Object |
| Business operation spanning multiple models |
Service Object (as waiting room) |
| Authorization rules |
Policy Object |
| Multi-channel notifications |
Delivery Object (Active Delivery) |
Remember: Services are a "waiting room" for code until proper abstractions emerge. Don't let app/services become a bag of random objects.
Refactoring Scenarios
Canonical before/after transformations for the most common layerification moves. The layerification plan workflow uses these as reference templates when proposing phases.
| Scenario |
Goal area |
Reference |
| Extract callbacks to service |
callbacks, after_create chains |
callbacks-to-service.md |
| Extract authorization to policy |
authorization, permissions |
authorization-to-policy.md |
| Extract query logic to query object |
complex scopes, reporting queries |
query-to-query-object.md |
| Extract Current from model |
Current.* in domain |
current-from-model.md |
| Decompose god object with associated objects |
god model, large User/Account |
god-object-decomposition.md |
| Replace implicit state machine |
timestamp-based status |
implicit-to-explicit-state-machine.md |
| Extract view logic to presenter |
template logic, formatting |
view-logic-to-presenter.md |
| Form object for complex input |
fat controllers, multi-model forms |
complex-input-to-form-object.md |
Slash Commands
These slash commands are available only when this skill is installed as a Claude Code plugin (/plugin install layered-rails@layered-rails-skills). When the skill is installed via skills.sh or any other path that delivers skills/layered-rails/ without the surrounding plugin, the commands won't be present — invoke the corresponding workflow directly (see Workflows) or just ask in plain language.
| Command |
Workflow |
Purpose |
/layered-rails:review |
review |
Review code changes from a layered architecture perspective |
/layered-rails:spec-test |
spec-test |
Run specification test on specific files |
/layered-rails:analyze |
analyze |
Full codebase abstraction-layer analysis |
/layered-rails:analyze-services |
analyze-services |
Audit app/services/ and service-like classes — conventions, clusters, layer hygiene, test consequences |
/layered-rails:analyze-callbacks |
analyze-callbacks |
Score model callbacks, find extraction candidates |
/layered-rails:analyze-gods |
analyze-gods |
Find god objects via churn × complexity |
/layered-rails:plan [goal] |
plan |
Plan gradual adoption of layered patterns |
/layered-rails:archspec |
archspec |
Generate and verify an Archspec.rb enforcing layer boundaries in CI |
Topic References
For deep dives on specific topics:
| Topic |
Reference |
| Authorization (RBAC, ABAC, policies) |
authorization.md |
| Notifications (multi-channel delivery) |
notifications.md |
| View Components |
view-components.md |
| AI Integration (LLM, agents, RAG, MCP) |
ai-integration.md |
| Configuration |
configuration.md |
| Callbacks (scoring, extraction) |
callbacks.md |
| Current Attributes |
current-attributes.md |
| Instrumentation (logging, metrics) |
instrumentation.md |
Gem References
For library-specific guidance:
| Gem |
Purpose |
Reference |
| action_policy |
Authorization framework |
action-policy.md |
| view_component |
Component framework |
view-component.md |
| anyway_config |
Typed configuration |
anyway-config.md |
| active_delivery |
Multi-channel notifications |
active-delivery.md |
| alba |
JSON serialization |
alba.md |
| workflow |
State machines |
workflow.md |
| rubanok |
Filter/transformation DSL |
rubanok.md |
| active_agent |
AI agent framework |
active-agent.md |
| active_job-performs |
Eliminate anemic jobs |
active-job-performs.md |
| archspec |
Enforce layer boundaries in CI (reference Archspec.rb config) |
archspec.md |
Extraction Signals
When to extract from models:
| Signal |
Metric |
Action |
| God object |
High churn × complexity |
Decompose into concerns, delegates, or separate models |
| Operation callback |
Score 1-2/5 |
Extract to service or event handler |
| Code-slicing concern |
Groups by artifact type |
Convert to behavioral concern or extract |
| Current dependency |
Model reads Current.* |
Pass as explicit parameter |
Callback Scoring:
| Type |
Score |
Keep? |
| Transformer (compute values) |
5/5 |
Yes |
| Normalizer (sanitize input) |
4/5 |
Yes |
| Utility (counter caches) |
4/5 |
Yes |
| Observer (side effects) |
2/5 |
Maybe |
| Operation (business steps) |
1/5 |
Extract |
See Extraction Signals Reference for detailed guide.
Model Organization
Recommended order within model files:
class User < ApplicationRecord
# 1. Gems/DSL extensions
has_secure_password
# 2. Associations
belongs_to :account
has_many :posts
# 3. Enums
enum :status, { pending: 0, active: 1 }
# 4. Normalization
normalizes :email, with: -> { _1.strip.downcase }
# 5. Validations
validates :email, presence: true
# 6. Scopes
scope :active, -> { where(status: :active) }
# 7. Callbacks (transformers only)
before_validation :set_defaults
# 8. Delegations
delegate :name, to: :account, prefix: true
# 9. Public methods
def full_name = "#{first_name} #{last_name}"
# 10. Private methods
private
def set_defaults
self.locale ||= I18n.default_locale
end
end
Success Checklist
Well-layered code:
Guidelines
- Use domain language - Name models after business concepts (Participant, not User; Cloud, not GeneratedImage)
- Patterns before abstractions - Let code age before extracting; premature abstraction is worse than duplication
- Services as waiting room - Don't let
app/services become permanent residence for code
- Explicit over implicit - Prefer explicit parameters over Current attributes
- Extraction thresholds - Consider extraction when methods exceed 15 lines or call external APIs
1---2name: layered-rails3description: Write, refactor, and review Rails code using layered architecture principles from "Layered Design for Ruby on Rails Applications". Use when writing or refactoring Rails code — models, controllers, services, jobs, mailers, policies, forms, query objects, presenters, view components, state machines, serializers, or AI/LLM features — to apply correct patterns and avoid layer violations; and when reviewing Rails code, PRs, or diffs for layer violations, fat controllers/models, anemic models, callback misuse, god objects, or specification-test failures. Triggers on "layered design", "architecture layers", "abstraction layer", "specification test", "layer violation", "fat controller/model", "god object", "anemic model", "extract service/callback/policy/concern", "service object", "form/policy/query/value object", "presenter", "view component", "state machine", "Active Delivery", "callback scoring", "Rails refactor/review", "Rails patterns/best practices", "archspec", "architecture linter/enforcement".4---56# Layered Rails78Design and review Rails applications using layered architecture principles.910## Quick Start1112Rails applications are organized into four architecture layers with **unidirectional data flow**:1314```15┌─────────────────────────────────────────┐16│ PRESENTATION LAYER │17│ Controllers, Views, Channels, Jobs* │18│ Forms, Filters, Presenters, Serializers │19└─────────────────────────────────────────┘20 ↓21┌─────────────────────────────────────────┐22│ APPLICATION LAYER │23│ Services, Policies, Mailers, Deliveries │24└─────────────────────────────────────────┘25 ↓26┌─────────────────────────────────────────┐27│ DOMAIN LAYER │28│ Models, Value Objects, Query Objects │29└─────────────────────────────────────────┘30 ↓31┌─────────────────────────────────────────┐32│ INFRASTRUCTURE LAYER │33│ Active Record, API Clients, Storage │34└─────────────────────────────────────────┘35```3637\* Jobs are **internal inbound** entry points: design-wise they follow the same rules as controllers, minus authentication and user-input handling.3839**Core Rule:** Lower layers must never depend on higher layers.4041See [Architecture Layers Reference](references/core/architecture-layers.md) for the full layer responsibilities and the Four Rules deep-dive.4243## What this skill is for4445Use this skill when:46471. **Analyzing a codebase** — apply the [architecture analysis](workflows/analyze.md) for a full audit, or zoom in with the [service-layer audit](workflows/analyze-services.md), [callback analysis](workflows/analyze-callbacks.md), or [god-object analysis](workflows/analyze-gods.md).482. **Reviewing code changes** — run the [code review workflow](workflows/review.md) on a diff, file, or branch.493. **Running the specification test** — use the [spec-test workflow](workflows/spec-test.md) on a single file or directory to evaluate whether code belongs in its current layer.504. **Planning gradual adoption** — generate a phased roadmap with the [layerification plan workflow](workflows/plan.md), focused on a goal like "introduce authorization" or "decompose god objects."515. **Planning a feature** — I'll apply the layered principles below to whichever code you're about to write.526. **Implementing a specific pattern** — authorization, notifications, view components, AI integration, etc. — see the Pattern Catalog and Topic References below.5354In Claude Code with this skill installed as a plugin (`/plugin install layered-rails@layered-rails-skills`), each workflow above is also reachable as a slash command — see [Slash Commands](#slash-commands). Natural-language requests ("review this file with layered-rails", "run the specification test on `app/models/order.rb`") work in any environment that has the skill loaded.5556## Workflows5758Reusable procedures bundled inside this skill. Read the file and apply it to the target code:5960- [Architecture analysis](workflows/analyze.md) — full layered-architecture audit of a Rails codebase61- [Code review](workflows/review.md) — review a diff or file set for layer violations62- [Specification test](workflows/spec-test.md) — evaluate whether code belongs in its current layer63- [Service-layer audit](workflows/analyze-services.md) — deep audit of `app/services/` and service-like classes (per-cluster proposals, contracts, layer hygiene)64- [Callback analysis](workflows/analyze-callbacks.md) — score Active Record callbacks and find extraction candidates65- [God-object analysis](workflows/analyze-gods.md) — identify oversized models and recommend decomposition66- [Gradual layerification plan](workflows/plan.md) — incremental roadmap for adopting layered patterns67- [ArchSpec setup](workflows/archspec.md) — generate and verify a tailored `Archspec.rb` enforcing the layer boundaries in CI6869## Core Principles7071### The Four Rules72731. **Unidirectional Data Flow** - Data flows top-to-bottom only742. **No Reverse Dependencies** - Lower layers never depend on higher layers753. **Abstraction Boundaries** - Each abstraction belongs to exactly one layer764. **Minimize Connections** - Fewer inter-layer connections = looser coupling7778### Common Violations7980| Violation | Example | Fix |81|-----------|---------|-----|82| Model uses Current | `Current.user` in model | Pass user as explicit parameter |83| Service accepts request | `param :request` in service | Extract value object from request |84| Controller has business logic | Pricing calculations in action | Extract to service or model |85| Anemic models | All logic in services | Keep domain logic in models |8687| Category | Reference |88|----------|-----------|89| Layer violations (Current in models, request in services, notifications in models, business logic in controllers) | [layer-violations.md](references/anti-patterns/layer-violations.md) |90| Service objects (anemic models, bag of random objects, premature abstraction) | [service-objects.md](references/anti-patterns/service-objects.md) |91| Callbacks (operation callbacks, skip callbacks, control flags) | [callbacks.md](references/anti-patterns/callbacks.md) |92| Concerns (code-slicing, overgrown) | [concerns.md](references/anti-patterns/concerns.md) |93| Helpers (HTML construction in helpers) | [helpers.md](references/anti-patterns/helpers.md) |94| Jobs (anemic jobs) | [jobs.md](references/anti-patterns/jobs.md) |95| Testing (testing wrong layer) | [testing.md](references/anti-patterns/testing.md) |9697### The Specification Test9899> If the specification of an object describes features beyond the primary responsibility of its abstraction layer, such features should be extracted into lower layers.100101**How to apply:**1021. List responsibilities the code handles1032. Evaluate each against the layer's primary concern1043. Extract misplaced responsibilities to appropriate layers105106See [Specification Test Reference](references/core/specification-test.md) for detailed guide.107108## Pattern Catalog109110| Pattern | Layer | Use When | Reference |111|---------|-------|----------|-----------|112| Service Object | Application | Orchestrating domain operations | [service-objects.md](references/patterns/service-objects.md) |113| Query Object | Domain | Complex, reusable queries | [query-objects.md](references/patterns/query-objects.md) |114| Form Object | Presentation | Multi-model forms, complex validation | [form-objects.md](references/patterns/form-objects.md) |115| Filter Object | Presentation | Request parameter transformation | [filter-objects.md](references/patterns/filter-objects.md) |116| Presenter | Presentation | View-specific logic, multiple models | [presenters.md](references/patterns/presenters.md) |117| Serializer | Presentation | API response formatting | [serializers.md](references/patterns/serializers.md) |118| Policy Object | Application | Authorization decisions | [policy-objects.md](references/patterns/policy-objects.md) |119| Value Object | Domain | Immutable, identity-less concepts | [value-objects.md](references/patterns/value-objects.md) |120| Collaborator Object | Domain | A slice of one model's behavior in a typed delegate | [collaborator-objects.md](references/patterns/collaborator-objects.md) |121| State Machine | Domain | States, events, transitions | [state-machines.md](references/patterns/state-machines.md) |122| Concern | Domain | Shared behavioral extraction | [concerns.md](references/patterns/concerns.md) |123| Repository | Domain | **Last resort** — returning custom domain objects mapped from AR data, after AR scopes (simple) and query objects (query building) are insufficient | [repositories.md](references/patterns/repositories.md) |124125### Pattern Selection Guide126127**"Where should this code go?"**128129| If you have... | Consider... |130|----------------|-------------|131| Complex multi-model form | Form Object |132| Request parameter filtering/transformation | Filter Object |133| View-specific formatting | Presenter |134| Complex database query used in multiple places | Query Object |135| Business operation spanning multiple models | Service Object (as waiting room) |136| Authorization rules | Policy Object |137| Multi-channel notifications | Delivery Object (Active Delivery) |138139**Remember:** Services are a "waiting room" for code until proper abstractions emerge. Don't let `app/services` become a bag of random objects.140141## Refactoring Scenarios142143Canonical before/after transformations for the most common layerification moves. The [layerification plan workflow](workflows/plan.md) uses these as reference templates when proposing phases.144145| Scenario | Goal area | Reference |146|----------|-----------|-----------|147| Extract callbacks to service | callbacks, after_create chains | [callbacks-to-service.md](examples/callbacks-to-service.md) |148| Extract authorization to policy | authorization, permissions | [authorization-to-policy.md](examples/authorization-to-policy.md) |149| Extract query logic to query object | complex scopes, reporting queries | [query-to-query-object.md](examples/query-to-query-object.md) |150| Extract Current from model | Current.* in domain | [current-from-model.md](examples/current-from-model.md) |151| Decompose god object with associated objects | god model, large User/Account | [god-object-decomposition.md](examples/god-object-decomposition.md) |152| Replace implicit state machine | timestamp-based status | [implicit-to-explicit-state-machine.md](examples/implicit-to-explicit-state-machine.md) |153| Extract view logic to presenter | template logic, formatting | [view-logic-to-presenter.md](examples/view-logic-to-presenter.md) |154| Form object for complex input | fat controllers, multi-model forms | [complex-input-to-form-object.md](examples/complex-input-to-form-object.md) |155156## Slash Commands157158These slash commands are available **only when this skill is installed as a Claude Code plugin** (`/plugin install layered-rails@layered-rails-skills`). When the skill is installed via [skills.sh](https://skills.sh/) or any other path that delivers `skills/layered-rails/` without the surrounding plugin, the commands won't be present — invoke the corresponding workflow directly (see [Workflows](#workflows)) or just ask in plain language.159160| Command | Workflow | Purpose |161|---------|----------|---------|162| `/layered-rails:review` | [review](workflows/review.md) | Review code changes from a layered architecture perspective |163| `/layered-rails:spec-test` | [spec-test](workflows/spec-test.md) | Run specification test on specific files |164| `/layered-rails:analyze` | [analyze](workflows/analyze.md) | Full codebase abstraction-layer analysis |165| `/layered-rails:analyze-services` | [analyze-services](workflows/analyze-services.md) | Audit `app/services/` and service-like classes — conventions, clusters, layer hygiene, test consequences |166| `/layered-rails:analyze-callbacks` | [analyze-callbacks](workflows/analyze-callbacks.md) | Score model callbacks, find extraction candidates |167| `/layered-rails:analyze-gods` | [analyze-gods](workflows/analyze-gods.md) | Find god objects via churn × complexity |168| `/layered-rails:plan [goal]` | [plan](workflows/plan.md) | Plan gradual adoption of layered patterns |169| `/layered-rails:archspec` | [archspec](workflows/archspec.md) | Generate and verify an `Archspec.rb` enforcing layer boundaries in CI |170171## Topic References172173For deep dives on specific topics:174175| Topic | Reference |176|-------|-----------|177| Authorization (RBAC, ABAC, policies) | [authorization.md](references/topics/authorization.md) |178| Notifications (multi-channel delivery) | [notifications.md](references/topics/notifications.md) |179| View Components | [view-components.md](references/topics/view-components.md) |180| AI Integration (LLM, agents, RAG, MCP) | [ai-integration.md](references/topics/ai-integration.md) |181| Configuration | [configuration.md](references/topics/configuration.md) |182| Callbacks (scoring, extraction) | [callbacks.md](references/topics/callbacks.md) |183| Current Attributes | [current-attributes.md](references/topics/current-attributes.md) |184| Instrumentation (logging, metrics) | [instrumentation.md](references/topics/instrumentation.md) |185186## Gem References187188For library-specific guidance:189190| Gem | Purpose | Reference |191|-----|---------|-----------|192| action_policy | Authorization framework | [action-policy.md](references/gems/action-policy.md) |193| view_component | Component framework | [view-component.md](references/gems/view-component.md) |194| anyway_config | Typed configuration | [anyway-config.md](references/gems/anyway-config.md) |195| active_delivery | Multi-channel notifications | [active-delivery.md](references/gems/active-delivery.md) |196| alba | JSON serialization | [alba.md](references/gems/alba.md) |197| workflow | State machines | [workflow.md](references/gems/workflow.md) |198| rubanok | Filter/transformation DSL | [rubanok.md](references/gems/rubanok.md) |199| active_agent | AI agent framework | [active-agent.md](references/gems/active-agent.md) |200| active_job-performs | Eliminate anemic jobs | [active-job-performs.md](references/gems/active-job-performs.md) |201| archspec | Enforce layer boundaries in CI (reference `Archspec.rb` config) | [archspec.md](references/gems/archspec.md) |202203## Extraction Signals204205**When to extract from models:**206207| Signal | Metric | Action |208|--------|--------|--------|209| God object | High churn × complexity | Decompose into concerns, delegates, or separate models |210| Operation callback | Score 1-2/5 | Extract to service or event handler |211| Code-slicing concern | Groups by artifact type | Convert to behavioral concern or extract |212| Current dependency | Model reads Current.* | Pass as explicit parameter |213214**Callback Scoring:**215| Type | Score | Keep? |216|------|-------|-------|217| Transformer (compute values) | 5/5 | Yes |218| Normalizer (sanitize input) | 4/5 | Yes |219| Utility (counter caches) | 4/5 | Yes |220| Observer (side effects) | 2/5 | Maybe |221| Operation (business steps) | 1/5 | Extract |222223See [Extraction Signals Reference](references/core/extraction-signals.md) for detailed guide.224225## Model Organization226227Recommended order within model files:228229```ruby230class User < ApplicationRecord231 # 1. Gems/DSL extensions232 has_secure_password233234 # 2. Associations235 belongs_to :account236 has_many :posts237238 # 3. Enums239 enum :status, { pending: 0, active: 1 }240241 # 4. Normalization242 normalizes :email, with: -> { _1.strip.downcase }243244 # 5. Validations245 validates :email, presence: true246247 # 6. Scopes248 scope :active, -> { where(status: :active) }249250 # 7. Callbacks (transformers only)251 before_validation :set_defaults252253 # 8. Delegations254 delegate :name, to: :account, prefix: true255256 # 9. Public methods257 def full_name = "#{first_name} #{last_name}"258259 # 10. Private methods260 private261262 def set_defaults263 self.locale ||= I18n.default_locale264 end265end266```267268## Success Checklist269270Well-layered code:271272- [ ] No reverse dependencies (lower layers don't depend on higher)273- [ ] Models don't access Current attributes274- [ ] Services don't accept request objects275- [ ] Controllers are thin (HTTP concerns only)276- [ ] Domain logic lives in models, not services277- [ ] Callbacks score 4+ or are extracted278- [ ] Concerns are behavioral, not code-slicing279- [ ] Abstractions don't span multiple layers280- [ ] Tests verify appropriate layer responsibilities281282## Guidelines283284- **Use domain language** - Name models after business concepts (Participant, not User; Cloud, not GeneratedImage)285- **Patterns before abstractions** - Let code age before extracting; premature abstraction is worse than duplication286- **Services as waiting room** - Don't let `app/services` become permanent residence for code287- **Explicit over implicit** - Prefer explicit parameters over Current attributes288- **Extraction thresholds** - Consider extraction when methods exceed 15 lines or call external APIs