Claude Code Plugins

Community-maintained marketplace

Feedback

Ruby language patterns and idioms. Use when writing Ruby code, reviewing diffs, or discussing Ruby style. Covers naming, conditionals, method organization, and the "fail loud" philosophy.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name ruby-idioms
description Ruby language patterns and idioms. Use when writing Ruby code, reviewing diffs, or discussing Ruby style. Covers naming, conditionals, method organization, and the "fail loud" philosophy.

Ruby Idioms

Patterns for clear, maintainable Ruby code.

Philosophy: Fail Loud, Not Silent

Code should fail loudly on invalid assumptions rather than mask problems. Silent failures hide bugs; exceptions reveal them early.

Trust Valid State

When context guarantees a value exists, don't add defensive nil checks:

# Context: This code only runs when current_user is set
# Good - trusts the context
order.user.charge(order.total)

# Avoid - defensive check masks potential bugs
order.user&.charge(order.total)

If order.user is unexpectedly nil, an exception reveals the programming error immediately.

Remove Unnecessary Guards

When refactoring, remove defensive checks that the calling context guarantees:

# If the view only renders when Current.user exists:
# Good
subscription = subscriptions.find { |s| s.user_id == Current.user.id }

# Unnecessary - masks bugs if assumption is wrong
subscription = subscriptions.find { |s| s.user_id == Current.user&.id }

Conditionals vs Guard Clauses

Prefer expanded conditionals for clarity. Use guard clauses only at method entry points.

Expanded Conditionals

# Preferred - clear flow, obvious return value
def todos_for_group
  if ids = params[:todo_ids]
    @bucket.todos.find(ids.split(","))
  else
    []
  end
end

# Avoid - guard clause for simple branching
def todos_for_group
  ids = params[:todo_ids]
  return [] unless ids
  @bucket.todos.find(ids.split(","))
end

Guard Clauses at Entry

Guards work well when returning early before substantial logic:

def after_commit(recording)
  return if recording.parent.was_created?

  if recording.was_created?
    broadcast_new(recording)
  else
    broadcast_change(recording)
  end
end

Naming Conventions

Explicit Over Brief

Names should reveal intent without requiring context:

# Good - explicit purpose
request_method         # not: method (avoids collisions)
stripe_discount_id     # not: discount_id
format_date_for_grouping  # not: format_date

# Good - describes what it does
def store_referrer_user(user)
def check_email_still_matches

Constants for Business Rules

Extract magic numbers and limits to named constants:

class Friendship < ApplicationRecord
  MAX_FRIENDS_PER_USER = 500

  validate :user_friend_limit_not_exceeded, on: :create

  private

  def user_friend_limit_not_exceeded
    if user.friendships.count >= MAX_FRIENDS_PER_USER
      errors.add :base, "Maximum friend limit reached"
    end
  end
end

Bang Methods

Only add ! when a non-bang alternative exists with different behavior:

# Correct - bang has non-bang counterpart
save! / save      # raises vs returns false
destroy! / destroy  # raises vs returns false

# Incorrect - no non-bang alternative
def process_payment!  # Don't use ! just because it's "dangerous"
  # ...
end

Method Organization

Order by Visibility and Call Sequence

class Order
  # 1. Class methods
  def self.find_recent
    where("created_at > ?", 1.week.ago)
  end

  # 2. Public instance methods (initialize first)
  def initialize(attrs)
    @attrs = attrs
  end

  def process
    validate_items
    calculate_total
    charge_customer
  end

  private
  # 3. Private methods in call order
  def validate_items
    # called first
  end

  def calculate_total
    # called second
  end

  def charge_customer
    # called third
  end
end

Visibility Modifier Formatting

No blank line after private/protected:

# Good
private
def helper_method
  # ...
end

# Avoid
private

def helper_method
  # ...
end

Rails Helpers Over Custom Code

Use built-in helpers:

# Time
time_ago_in_words(created_at)
distance_of_time_in_words(start_time, end_time)

# Presence
name.presence || "Anonymous"  # not: name.blank? ? "Anonymous" : name

# Inclusion
status.in?(%w[active pending])  # not: %w[active pending].include?(status)

# Delegation
delegate :name, :email, to: :user

Quick Reference

Do Avoid
Let invalid state raise exceptions Defensive nil chains everywhere
Expanded conditionals in method bodies Guard clauses for simple branching
Guards at method entry before substantial logic Guards scattered throughout
Explicit, descriptive names Abbreviated or generic names
Constants for business rules Magic numbers inline
! only with non-bang counterpart ! to indicate "dangerous"
Private methods in call order Random private method ordering