Curated library of AI agent skills for Ruby on Rails development. Covers code review, architecture, security, testing (RSpec), engines, service objects, DDD patterns, and workflow automation.
73
91%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Use this skill when the task is to move existing code out of a Rails app and into an engine.
Prefer incremental extraction over big-bang rewrites. Preserve behavior first, then improve design.
DO NOT extract and change behavior in the same step. Extraction must preserve existing behavior; refactoring and improvements belong in a separate step after the move is complete and verified.
| Extraction Step | Action |
|---|---|
| Identify bounded feature | Choose one coherent responsibility to extract |
| List host dependencies | Document models, services, config the feature needs |
| Define engine boundary | Decide what lives in engine vs host |
| Move stable logic first | POROs, services, value objects before controllers |
| Add adapters | Replace direct host references with config or adapter interfaces |
| Move UI/routes last | Controllers, views, routes only after seams are clear |
| Keep tests green | Regression coverage throughout each slice |
| Mistake | Reality |
|---|---|
| Extracting too much at once | One bounded slice per step; large extractions hide bugs and are hard to revert |
| Direct host references in engine | Engine must use adapters or config; direct constants couple engine to host internals |
| No adapter layer | Without adapters, host model changes break the engine; introduce seams before moving |
Start with:
Delay these until later:
Replace hardcoded host dependencies with:
Do not move code into an engine if it still depends on many private host internals.
First slice (move PORO, no host model yet):
Extract Pricing::Calculator from app/services/pricing/calculator.rb into the engine. It only depends on LineItem and Discount — move those to the engine as engine models in the same slice, or keep them in the host and inject via an adapter in a later slice.
Adapter for host dependency:
# In engine: use config instead of hardcoded User
# Before (in app): OrderCreator.new(current_user).call
# After (in engine): OrderCreator.new(MyEngine.config.current_user_provider.call(request)).call
# Host sets in initializer: MyEngine.config.current_user_provider = ->(req) { req.env["current_user"] }Red flag: Extracting OrdersController in the first slice while it still calls User, Tenant, and AuditLog — too many host ties. Extract the service/PORO first and introduce adapters, then move the controller.
When asked to extract code:
| Skill | When to chain |
|---|---|
| rails-engine-author | Engine structure, host contract, namespace design after extraction |
| rails-engine-testing | Dummy app, regression tests, integration verification |
| refactor-safely | Behavior-preserving refactors before or after extraction slices |
api-rest-collection
create-prd
ddd-boundaries-review
ddd-rails-modeling
ddd-ubiquitous-language
generate-tasks
rails-agent-skills
rails-architecture-review
rails-background-jobs
rails-bug-triage
rails-code-conventions
rails-code-review
rails-engine-compatibility
rails-engine-docs
rails-engine-extraction
rails-engine-installers
rails-engine-release
rails-engine-reviewer
rails-engine-testing
rails-graphql-best-practices
rails-migration-safety
rails-review-response
rails-security-review
rails-stack-conventions
rails-tdd-slices
refactor-safely
rspec-best-practices
rspec-service-testing
ruby-api-client-integration
ruby-service-objects
strategy-factory-null-calculator
ticket-planning
yard-documentation