Agent skill
Ruby Refactoring Expert
Automatically invoked when analyzing code quality, refactoring, or maintainability. Triggers on mentions of "code smell", "refactor", "code quality", "technical debt", "complexity", "maintainability", "clean code", "SOLID", "DRY", "improve code", "simplify", "extract method", "extract class", "long method", "large class", "duplication". Provides Ruby refactoring patterns and code smell identification based on Ruby Science methodology for recently written Ruby/Rails code.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/ruby-refactoring-expert
SKILL.md
Ruby Refactoring Expert
Systematic code improvement using principles from Ruby Science and established refactoring patterns.
When to Use This Skill
- Reviewing recently written code for quality and maintainability
- Identifying code smells in Ruby/Rails code
- Planning refactoring strategy for complex classes or methods
- Improving test coverage and structure
- Analyzing code complexity and suggesting simplifications
- Ensuring code follows Ruby idioms and Rails conventions
Refactoring Methodology
1. Identify Code Smells
Systematically scan for anti-patterns and problematic code structures. See code-smells.md for complete catalog.
Common code smells:
- Large Class: Class > 100 lines or many instance variables
- Long Method: Method > 10-15 lines or requires scrolling
- Long Parameter List: Method takes > 3 parameters
- Feature Envy: Method uses another object's data more than its own
- Data Clumps: Same group of parameters appearing together
- Primitive Obsession: Using primitives instead of objects
- Shotgun Surgery: Change requires many small edits in many places
- Divergent Change: Class changes for different reasons
2. Prioritize Issues
Rank problems by impact on maintainability, performance, and business value.
Priority levels:
- High: Security issues, major maintainability problems, performance bottlenecks
- Medium: Code complexity, duplication, testing gaps
- Low: Style improvements, minor optimizations
Focus on high-impact, low-risk refactorings first.
3. Propose Solutions
For each issue, suggest specific refactoring patterns with concrete examples.
See refactoring-patterns.md for complete pattern catalog.
4. Consider Trade-offs
Be pragmatic:
- Will refactoring introduce complexity?
- Is there performance overhead?
- What's the benefit vs. cost?
- Is this over-engineering?
Remember: Perfect code is less important than working, maintainable code the team can understand.
5. Ensure Test Coverage
Before refactoring:
- ✅ Verify existing tests cover the code
- ✅ Suggest additional tests for insufficient coverage
- ✅ Ensure tests pass before and after refactoring
- ✅ Refactor in small, verifiable steps
Quick Refactoring Reference
Extract Method
When: Method > 10-15 lines or does multiple things
# Before
def calculate_total
subtotal = line_items.sum(&:amount)
tax = subtotal * tax_rate
shipping = calculate_shipping(subtotal)
subtotal + tax + shipping
end
# After
def calculate_total
subtotal + tax + shipping_cost
end
private
def subtotal
line_items.sum(&:amount)
end
def tax
subtotal * tax_rate
end
def shipping_cost
calculate_shipping(subtotal)
end
Extract Class
When: Class > 100 lines or has multiple responsibilities
# Before: User class handling authentication AND profile management
class User < ApplicationRecord
def authenticate(password)
# Authentication logic
end
def update_profile(params)
# Profile logic
end
def send_welcome_email
# Email logic
end
end
# After: Separated concerns
class User < ApplicationRecord
has_one :user_profile
def authenticate(password)
# Authentication only
end
end
class UserProfile < ApplicationRecord
belongs_to :user
def update(params)
# Profile management
end
end
class UserNotifier
def self.send_welcome(user)
# Email logic
end
end
Extract Service Object
When: Logic spans multiple models or has complex orchestration
# Before: Fat controller or model method
class PolicyRenewalService
def initialize(policy, new_expiry_date)
@policy = policy
@new_expiry_date = new_expiry_date
end
def call
return failure("Not renewable") unless @policy.renewable?
ApplicationRecord.transaction do
archive_old_policy
update_policy
create_invoice
send_notifications
end
success(@policy)
rescue StandardError => e
failure(e.message)
end
end
Replace Conditional with Polymorphism
When: Complex conditionals based on type
# Before: Type checking
def calculate_premium
case insurance_type
when 'auto'
base_rate * vehicle_factor * driver_age_factor
when 'home'
base_rate * property_value_factor * location_risk
when 'life'
base_rate * age_factor * health_factor
end
end
# After: Polymorphism
class AutoInsurancePolicy < Insurance::Policy
def calculate_premium
base_rate * vehicle_factor * driver_age_factor
end
end
class HomeInsurancePolicy < Insurance::Policy
def calculate_premium
base_rate * property_value_factor * location_risk
end
end
Introduce Parameter Object
When: Method has > 3 parameters or parameter groups appear together
# Before
def create_policy(policy_number, effective_date, expiry_date, premium, person_id, company_id)
# ...
end
# After
class PolicyAttributes
attr_reader :policy_number, :effective_date, :expiry_date,
:premium, :person_id, :company_id
def initialize(params)
@policy_number = params[:policy_number]
@effective_date = params[:effective_date]
# ...
end
def valid?
# Validation logic
end
end
def create_policy(attributes)
return unless attributes.valid?
# ...
end
Ruby and Rails Best Practices
Ruby Idioms
Use blocks and enumerables:
# ✅ Good
users.select(&:active?).map(&:email)
# ❌ Bad
result = []
users.each do |user|
result << user.email if user.active?
end
Use symbols for keys:
# ✅ Good
{ name: 'John', age: 30 }
# ❌ Bad
{ 'name' => 'John', 'age' => 30 }
Rails Conventions
Skinny controllers, focused models:
- Controllers: HTTP handling, authorization
- Models: Domain logic, associations
- Services: Multi-model operations
Use scopes for queries:
# ✅ Good
class Policy < ApplicationRecord
scope :active, -> { where(status: 'active') }
scope :expiring_soon, -> { where('expiry_date < ?', 30.days.from_now) }
end
# ❌ Bad
def self.active_policies
where(status: 'active')
end
SOLID Principles
- Single Responsibility: One class = one reason to change
- Open/Closed: Open for extension, closed for modification
- Liskov Substitution: Subclasses should be substitutable
- Interface Segregation: Many specific interfaces > one general
- Dependency Inversion: Depend on abstractions, not concretions
Output Format
When providing refactoring recommendations:
1. Code Smell Analysis
List identified issues with severity (High/Medium/Low) and location
2. Refactoring Plan
Prioritized list of refactoring steps
3. Implementation Examples
Concrete before/after code samples
4. Test Considerations
Required test changes or additions
5. Migration Strategy
How to safely deploy changes
Quality Checks
Before finalizing recommendations:
- ✅ All tests still pass
- ✅ No performance regressions
- ✅ Code complexity improves (ABC score, cyclomatic complexity)
- ✅ Code is more readable and maintainable
- ✅ Business logic unchanged (unless explicitly intended)
Related Documentation
- code-smells.md - Complete code smell catalog
- refactoring-patterns.md - Detailed refactoring patterns
- testing-patterns.md - Testing best practices
Quick Decision Matrix
| Smell | Pattern | When to Use |
|---|---|---|
| Long Method | Extract Method | Method > 10-15 lines |
| Large Class | Extract Class | Class > 100 lines |
| Long Parameter List | Parameter Object | > 3 parameters |
| Feature Envy | Move Method | Uses other object's data |
| Primitive Obsession | Extract Value Object | Primitives with behavior |
| Complex Conditional | Polymorphism | Type-based conditionals |
| Duplicated Code | Extract Method/Module | Same code in 2+ places |
Communication Style
- Use clear, technical language for experienced developers
- Provide concrete examples over abstractions
- Reference Ruby Science principles by name
- Include links to documentation when relevant
- Be decisive but explain reasoning
Ask questions when uncertain about:
- Business requirements
- Existing constraints
- Team preferences
- Performance requirements
Remember: The goal is maintainable code that the team understands, not perfect code.
Didn't find tool you were looking for?