Curated library of 41 public AI agent skills for Ruby on Rails development. Organized by category: planning, testing, code-quality, ddd, engines, infrastructure, api, patterns, context, and orchestration. Covers code review, architecture, security, testing (RSpec), engines, service objects, DDD patterns, and TDD automation. Repository workflows remain documented in GitHub but are intentionally excluded from the Tessl tile.
95
93%
Does it follow best practices?
Impact
96%
1.77xAverage score across 41 eval scenarios
Passed
No known issues
One API for the client: Calculator::Factory.for(entity).calculate. The factory picks the strategy; NullService handles unknown variants safely.
| Component | Responsibility |
|---|---|
| Factory | Dispatch to correct service class via SERVICE_MAP; fall back to NullService |
| BaseService | Guard with should_calculate?; delegate to compute_result |
| NullService | Always returns nil safely — never raises |
| Concrete | Override should_calculate? (add variant check on top of super) and compute_result |
Tests Gate Implementation
For each component (Factory → BaseService → NullService → Concrete):
1. Write the spec — contexts per variant, plus the NullService path
2. Run it — verify it fails because the component does not exist yet
3. Implement the component — minimum code to make the spec pass
4. Run again — confirm green, then proceed to the next component
Each component gets its own RED command/output and GREEN command/output before
the next component starts. Do not collapse NullService and concrete services
into a single verification step.NullService.calculate that delegates to compute_result if should_calculate? is true.should_calculate? and nil for compute_result.should_calculate? and compute_result. Always call super in should_calculate?.Factory.for(entity) is the only permitted access path.File Structure
app/services/<calculator_name>/
├── factory.rb
├── base_service.rb
├── null_service.rb
├── standard_service.rb
├── premium_service.rb1. Factory
# frozen_string_literal: true
module PricingCalculator
class Factory
SERVICE_MAP = {
'standard' => StandardPricingService,
'premium' => PremiumPricingService
}.freeze
def self.for(order)
plan = order.plan
return NullService.new(order) unless plan&.active?
service_class = SERVICE_MAP[plan.name] || NullService
service_class.new(order)
end
end
end2. BaseService
# frozen_string_literal: true
module PricingCalculator
class BaseService
def initialize(order)
@order = order
end
def calculate
return nil unless should_calculate?
compute_result
end
private
def should_calculate?
@order.present?
end
def compute_result
raise NotImplementedError, "#{self.class}#compute_result must be implemented"
end
end
end3. NullService
# frozen_string_literal: true
module PricingCalculator
class NullService < BaseService
private
def should_calculate?
false
end
def compute_result
nil
end
end
end4. Concrete Service Example
# frozen_string_literal: true
module PricingCalculator
class StandardPricingService < BaseService
private
def should_calculate?
super && @order.plan.name == 'standard'
end
def compute_result
@order.base_price * 1.0
end
end
end5. Usage
price = PricingCalculator::Factory.for(order).calculate6. Tests (RSpec) Each spec suite must cover: inactive plan, nil plan, each named variant, and unknown variant. Mirror the same context structure across Factory, NullService, and every concrete service. If a concrete service should not handle an unknown variant, assert that it returns nil through the guard rather than calculating.
Pitfalls
| Pitfall | Fix |
|---|---|
| SERVICE_MAP key mismatch | Verify keys match exactly what is stored in the database — typos cause silent NullService fallbacks |
| Missing NullService spec | Always add a spec context for unknown/nil variants or tests will never catch the fallback regression |
Direct service instantiation (ServiceClass.new(entity)) | Route through Factory.for(entity) — it is the sole public entry point; direct instantiation bypasses the NullService safety net |
Forgetting super in concrete should_calculate? | Always call super — skipping it removes the base nil/presence guard |
Calculator::Factory.for(entity).calculate as the only public access path.SERVICE_MAP keys, concrete classes, and unknown/nil fallback to NullService.super call, and NullService no-op behavior.calculate, should_calculate?, or compute_result contract| Skill | When to chain |
|---|---|
| test-service | For complete Factory, BaseService, NullService, and concrete strategy specs |
| create-service-object | For naming conventions, YARD docs, and frozen_string_literal baseline |
docs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10
scenario-11
scenario-12
scenario-13
scenario-14
scenario-15
scenario-16
scenario-17
scenario-18
scenario-19
scenario-20
scenario-21
scenario-22
scenario-23
scenario-24
scenario-25
scenario-26
scenario-27
scenario-28
scenario-29
scenario-30
scenario-31
scenario-32
scenario-33
scenario-34
scenario-35
scenario-36
scenario-37
scenario-38
scenario-39
scenario-40
scenario-41
mcp_server
skills
api
generate-api-collection
implement-graphql
code-quality
apply-code-conventions
apply-stack-conventions
assets
snippets
code-review
refactor-code
respond-to-review
review-architecture
security-check
context
load-context
setup-environment
ddd
define-domain-language
model-domain
review-domain-boundaries
engines
create-engine
create-engine-installer
document-engine
extract-engine
release-engine
review-engine
test-engine
upgrade-engine
infrastructure
implement-background-job
implement-hotwire
optimize-performance
review-migration
seed-database
version-api
orchestration
skill-router
patterns
create-service-object
implement-calculator-pattern
write-yard-docs
planning
create-prd
generate-tasks
plan-tickets
testing
plan-tests
test-service
triage-bug
write-tests
workflows