From rails
This skill should be used when the user wants to refactor Ruby on Rails code by extracting service objects, concerns, query objects, form objects, or DelegateClass wrappers. Identifies code smells and applies established Rails refactoring patterns. Activates on: "refactor", "extract service", "extract concern", "fat model", "fat controller", "code smell", "service object", "query object", "form object", "too complex", "simplify", "extract class", "single responsibility", "rails refactor", "clean up code", "rifattorizzare", "estrarre servizio".
npx claudepluginhub fabn/claude-plugins --plugin railsThis skill uses the workspace's default tool permissions.
Identify code smells in Rails applications and apply established refactoring patterns. Extracts service objects, concerns, query objects, form objects, and DelegateClass wrappers following project conventions.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Identify code smells in Rails applications and apply established refactoring patterns. Extracts service objects, concerns, query objects, form objects, and DelegateClass wrappers following project conventions.
Reference files: Consult reference/patterns.md for complete code examples of each extraction pattern.
Read the code the user wants to refactor and identify the smell:
| Code Smell | Indicator | Extraction Target |
|---|---|---|
| Fat controller | Controller action > 15 lines, business logic in controller | Service object |
| Fat model | Model file > 200 lines, mixed responsibilities | Concern or service |
| Repeated query patterns | Same .where().order().limit() chain in multiple places | Query object / scope |
| Complex form handling | Multi-model form, conditional validations | Form object |
| Decorator logic | Display formatting, computed properties in model | DelegateClass wrapper |
| Callback chains | Long before_save / after_create chains with side effects | Service object |
| God service | Service > 100 lines, doing too many things | Split into focused services |
Before creating any new files, find existing patterns:
Service objects: Check app/services/ for naming and structure
Glob: app/services/**/*.rb
Look for:
initialize with kwargs? Positional args?.call class method? Instance #call? Custom method names?SemanticLogger::Loggable? Rails.logger?ActiveRecord::RecordInvalid?Concerns: Check app/models/concerns/ for naming and style
Glob: app/models/concerns/**/*.rb
Namespacing: Check if services are namespaced by domain
ls app/services/ (look for subdirectories)
Read project CLAUDE.md for explicit style conventions
Present the refactoring plan to the user before making changes:
## Refactoring Plan
**Current**: OrdersController#create (45 lines, handles validation, payment, notification)
**Proposed**:
1. Extract `OrderCreationService` to `app/services/order_creation_service.rb`
- Handles: validation, payment processing, order creation
- Returns: the created Order or raises on failure
2. Slim controller to: instantiate service, call, respond
**Files to create:**
- app/services/order_creation_service.rb
- spec/services/order_creation_service_spec.rb
**Files to modify:**
- app/controllers/api/orders_controller.rb (slim down #create)
Wait for user approval before proceeding.
Apply the appropriate pattern from reference/patterns.md:
extend ActiveSupport::Concernincluded block for class-level declarations.all)DelegateClass(ModelName) to wrap the modelsave, update)After extracting code:
After applying changes:
Run affected specs:
bundle exec rspec spec/services/new_service_spec.rb spec/controllers/affected_controller_spec.rb
Run RuboCop on new and changed files:
bundle exec rubocop app/services/new_service.rb app/controllers/affected_controller.rb
Check for loose ends:
Suggest next steps:
| Situation | Action |
|---|---|
| No existing service pattern in project | Use the standard initialize + method pattern, explain the convention |
| Mixed concerns hard to separate | Suggest incremental extraction — start with the most cohesive group |
| Circular dependencies after extraction | Suggest dependency injection or event-driven approach |
| Tests break after extraction | Check for missing let definitions, factory changes, or mock updates |
| RuboCop violations in new code | Fix before presenting to user |
| User disagrees with extraction boundary | Discuss trade-offs, adjust the plan |
reference/patterns.md — Complete code examples for service objects, concerns, query objects, form objects, and DelegateClass wrappers with before/after comparisons