skills/rails-service-patterns/SKILL.md
Analyzes and recommends Rails service object patterns for business logic extraction including command objects, result objects, form objects, query objects, and external API integration. Use when extracting logic from controllers/models, orchestrating multi-step workflows, or organizing app/services. NOT for simple CRUD, model validations, controller routing, or background job scheduling.
npx skillsauth add ag0os/rails-dev-plugin rails-service-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Analyze and recommend patterns for extracting and organizing business logic in Rails applications.
This skill forks on Axis A — logic placement. Before recommending where logic goes:
rails-stack-profiles (Axis A only — native or extracted).native → extraction.native.mdextracted → extraction.extracted.mdIf the axis cannot be resolved, default to native and state the assumption.
Everything else in this file is invariant — it holds regardless of axis.
| Pattern | Use When | Entry Point |
|---------|----------|-------------|
| Basic Service | Single operation with transaction | CreateOrder.new(...).call |
| Result Object | Caller needs success/failure + data | Result.new(success?: true, data:) |
| Form Object | Multi-model form submissions | RegistrationForm.new(params).save |
| Query Object | Complex reusable queries | UserSearchQuery.new(scope).call |
| Policy Object | Authorization decisions | PostPolicy.new(user, post).update? |
native axisextracted axisCreateOrder, SendInvitation -- never OrderService or UserManagercall (or perform)Use Struct.new(keyword_init: true) for lightweight results. Never raise exceptions for expected failures (validation, auth, payment decline).
class AuthenticateUser
Result = Struct.new(:success?, :user, :error, keyword_init: true)
def initialize(email:, password:)
@email = email
@password = password
end
def call
user = User.find_by(email: @email)
if user&.authenticate(@password)
Result.new(success?: true, user: user)
else
Result.new(success?: false, error: "Invalid credentials")
end
end
end
See patterns.md for the enhanced monad-like ServiceResult with on_success/on_failure chaining.
| Anti-Pattern | Problem | Fix |
|-------------|---------|-----|
| God service (100+ lines) | Does too much | Split into composable services |
| Raising exceptions for flow control | Expensive, hard to handle | Use Result objects |
| Deep service-calls-service chains | Hidden coupling | Orchestrate from controller or coordinator |
| self.call class method pattern | No instance state, limits DI | Use instance methods with constructor DI |
| No return value | Caller can't react to failures | Always return Result or meaningful value |
| Service modifying passed-in objects | Surprising side effects | Return new objects or be explicit |
| VerbNoun naming violation (UserService) | Unclear responsibility, attracts god service | One service = one operation = one verb |
When analyzing or creating services, provide:
development
WHAT: Language-agnostic corrective guidance for the refactoring phase. WHEN: Agent is restructuring code, fixing code smells, reducing complexity, or improving maintainability. NOT FOR: Writing new features, debugging runtime errors, performance tuning, or object design decisions.
tools
Analyzes Rails view templates, partials, layouts, helpers, and form patterns for best practices. Use when reviewing ERB templates, improving view performance with fragment caching, fixing form helpers, organizing partials, adding accessibility attributes, or evaluating collection rendering. NOT for Stimulus/Turbo logic (use hotwire-patterns), controller concerns, or API-only responses.
testing
Analyzes Rails test suites and recommends testing best practices for RSpec and Minitest. Use when writing new tests, reviewing test coverage, fixing flaky tests, improving test performance, choosing between test types (unit, integration, system, request), or setting up factories and fixtures. NOT for production monitoring, deployment verification, or load/stress testing infrastructure.
development
Detects a Rails project's architecture axes — logic placement (native vs extracted) and delivery (html vs api) — so other skills load profile-appropriate guidance without inline conditionals. Use when planning architecture or when a recommendation depends on where business logic lives or whether the app renders HTML or serves JSON. NOT for test framework, job backend, cache store, or auth library choices — those are orthogonal facts detected by project-conventions.