Automatically detect and suggest common Ruby patterns when working with Ruby code.
Automatically detects Ruby code smells and suggests proven design patterns like Data Objects, Service Objects, and Null Objects. Activates when reading, editing, or refactoring Ruby files to improve code quality and maintainability.
/plugin marketplace add jwplatta/prompt-library/plugin install rubyist@jwplatta-claude-toolsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
scripts/README.mdscripts/rubocop_summary.shscripts/run_rubocop.shAutomatically detect and suggest common Ruby patterns when working with Ruby code.
This skill activates when:
Detect:
to_h or to_json methodsSuggest:
class DataObject
# Add .build class method for construction
def self.build(attributes)
new(
name: attributes[:name],
email: attributes[:email]
)
end
# Add serialization
def to_h
{
name: name,
email: email
}
end
# Add factory methods
def self.from_json(json)
build(JSON.parse(json, symbolize_names: true))
end
def self.from_h(hash)
build(hash)
end
end
Detect:
Suggest:
# Create shared Loggable module
module Loggable
def logger
@logger ||= Logger.new(STDOUT).tap do |log|
log.progname = self.class.name
log.level = ENV.fetch('LOG_LEVEL', 'INFO')
end
end
end
# Include in classes
class MyClass
include Loggable
def process
logger.info "Processing started"
# ...
logger.debug "Details: #{details}"
end
end
Detect:
Suggest:
# Define custom exceptions
module MyApp
class Error < StandardError; end
class NotFoundError < Error; end
class ValidationError < Error; end
class AuthenticationError < Error; end
end
# Use specific exceptions
class UserService
def find(id)
user = repository.find(id)
raise MyApp::NotFoundError, "User #{id} not found" unless user
user
end
def authenticate(credentials)
raise MyApp::ValidationError, "Invalid credentials" if invalid?(credentials)
# ...
rescue SomeExternalError => e
raise MyApp::AuthenticationError, "Auth failed: #{e.message}"
end
end
Detect:
Suggest:
# Before - hard-coded dependency
class OrderProcessor
def process(order)
mailer = EmailMailer.new
mailer.send_confirmation(order)
end
end
# After - injected dependency
class OrderProcessor
def initialize(mailer: EmailMailer.new)
@mailer = mailer
end
def process(order)
@mailer.send_confirmation(order)
end
end
# Easy to test with mock
processor = OrderProcessor.new(mailer: MockMailer.new)
Detect:
try or &. operators used extensivelySuggest:
# Create Null Object
class NullUser
def name
"Guest"
end
def email
nil
end
def admin?
false
end
def null?
true
end
end
# Use in code
class Session
def current_user
@current_user || NullUser.new
end
end
# No more nil checks needed
session.current_user.name # Returns "Guest" instead of raising error
Detect:
Suggest:
# Before - primitive obsession
def send_email(email_string)
raise "Invalid email" unless email_string =~ /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
# ...
end
# After - Value Object
class Email
attr_reader :value
def initialize(value)
@value = value.to_s.downcase.strip
validate!
end
def ==(other)
value == other.value
end
def to_s
value
end
private
def validate!
raise ArgumentError, "Invalid email: #{value}" unless valid?
end
def valid?
value =~ /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
end
end
def send_email(email)
# Email already validated
mailer.send(to: email.to_s)
end
Detect:
Suggest:
# Extract to Query Object
class ActiveUsersQuery
def initialize(relation = User.all)
@relation = relation
end
def call
@relation
.where(active: true)
.where('last_login_at > ?', 30.days.ago)
.order(created_at: :desc)
end
end
# Usage
active_users = ActiveUsersQuery.new.call
recent_active_users = ActiveUsersQuery.new(User.where('created_at > ?', 1.week.ago)).call
Detect:
Suggest:
class CreateOrderService
def initialize(user:, items:, payment_method:)
@user = user
@items = items
@payment_method = payment_method
end
def call
ActiveRecord::Base.transaction do
order = create_order
process_payment(order)
send_confirmation(order)
order
end
rescue PaymentError => e
handle_payment_failure(e)
end
private
attr_reader :user, :items, :payment_method
def create_order
# ...
end
def process_payment(order)
# ...
end
def send_confirmation(order)
# ...
end
end
# Usage
result = CreateOrderService.new(
user: current_user,
items: cart.items,
payment_method: params[:payment_method]
).call
When a pattern is detected, respond with:
Pattern Detected: [Pattern Name]
I noticed [specific code smell or opportunity].
This is a good opportunity to use the [Pattern Name] pattern, which:
Would you like me to refactor this code to use this pattern?
[Show brief before/after example]
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.