# Ruby

> Use when writing, reviewing, or debugging pure Ruby code — idiomatic patterns, modern 3.x+ features (pattern matching, Data.define, endless methods), error handling conventions (raise vs fail, result objects), memoization, and performance idioms. For Rails use rails-guides. For testing use minitest. For code style use sandi-metz-rules.

- **Type:** Skill
- **Install:** `agentstack add skill-zarpay-rails-template-ruby`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [zarpay](https://agentstack.voostack.com/s/zarpay)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [zarpay](https://github.com/zarpay)
- **Source:** https://github.com/zarpay/rails-template/tree/main/files/.claude/skills/ruby

## Install

```sh
agentstack add skill-zarpay-rails-template-ruby
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Ruby Language Skill

## Overview

Opinionated Ruby conventions and idioms for writing idiomatic Ruby 3.x+ code. Focuses on patterns agents miss by default — the Weirich raise/fail distinction, safe nil-aware memoization, result objects over exceptions for expected failures, and performance-conscious enumeration.

## Error Handling Conventions

### Weirich raise/fail Convention

Use `fail` for first-time exceptions, `raise` only for re-raising:

```ruby
def process(order)
  fail ArgumentError, "Order cannot be nil" if order.nil?

  begin
    gateway.charge(order)
  rescue PaymentError => e
    logger.error("Payment failed: #{e.message}")
    raise  # re-raise with raise
  end
end
```

### Custom Exception Hierarchies

Group domain exceptions under a base error:

```ruby
module MyApp
  class Error  e
  fallback ? fallback.call(e) : raise
end

user = fetch_user(999) { |_| User.new(name: "Guest") }
```

See `references/error_handling.md` for full patterns and retry strategies.

## Modern Ruby (3.x+)

### Pattern Matching

```ruby
case response
in { status: 200, body: { users: [{ name: }, *] } }
  "First user: #{name}"
in { status: (400..), error: message }
  "Error: #{message}"
end

# Find pattern
case array
in [*, String => str, *]
  "Found string: #{str}"
end

# Pin operator
expected = 200
case response
in { status: ^expected, body: }
  process(body)
end
```

### Other 3.x+ Features

```ruby
# Endless methods (3.0+)
def square(x) = x * x
def admin? = role == "admin"

# Numbered block parameters (2.7+)
[1, 2, 3].map { _1 * 2 }

# Data class - immutable value objects (3.2+)
Point = Data.define(:x, :y)
p = Point.new(x: 1, y: 2)
p.with(x: 3)  # => Point(x: 3, y: 2)

# Hash#except (3.0+)
params.except(:password, :admin)

# filter_map (2.7+) - select + map in one pass
users.filter_map { |u| u.email if u.active? }

# tally (2.7+)
%w[a b a c b a].tally  # => {"a"=>3, "b"=>2, "c"=>1}
```

See `references/modern_ruby.md` for ractors, fiber scheduler, RBS types, and advanced pattern matching.

## Performance Quick Wins

### Frozen String Literals

```ruby
# frozen_string_literal: true
# Add to top of every file. Prevents mutation, reduces allocations.
# When you need mutable: String.new("hello") or +"hello"
```

### Efficient Enumeration

```ruby
# each_with_object for building results (avoids intermediate arrays)
totals = items.each_with_object(Hash.new(0)) do |item, hash|
  hash[item.category] += item.amount
end

# Lazy enumerables for large/infinite sequences
(1..Float::INFINITY).lazy.select(&:odd?).map { _1 ** 2 }.first(10)
```

### Memoization with nil/false Caveat

```ruby
# Simple (only works if result is truthy)
def users = @users ||= User.all.to_a

# Safe (handles nil/false results)
def feature_enabled?
  return @feature_enabled if defined?(@feature_enabled)
  @feature_enabled = expensive_check
end
```

### String Building

```ruby
# Bad: O(n^2) with +=
result = ""; items.each { |i| result += i.to_s }

# Good: O(n) with <<
result = String.new; items.each { |i| result << i.to_s }

# Best: join
items.map(&:to_s).join
```

See `references/performance.md` for YJIT, GC tuning, benchmarking, and profiling tools.

## Ruby Idioms to Prefer

### Guard Clauses

```ruby
def process(value)
  return unless value
  return unless value.valid?
  # main logic here
end
```

### Literal Array Constructors

```ruby
STATES = %w[draft published archived]      # word array
FIELDS = %i[name email created_at]         # symbol array
```

### Hash#fetch for Required Keys

```ruby
config.fetch(:api_key)                     # raises KeyError if missing
config.fetch(:timeout, 30)                 # default value
config.fetch(:handler) { build_handler }   # lazy default
```

### Safe Navigation

```ruby
user&.profile&.avatar_url  # returns nil if any link is nil
```

### Predicate and Bang Conventions

- `?` suffix: returns boolean (`empty?`, `valid?`, `admin?`)
- `!` suffix: dangerous version - mutates receiver or raises on failure (`save!`, `sort!`)
- Always provide a non-bang alternative when defining bang methods

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| `raise` for new exceptions | Use `fail`; reserve `raise` for re-raising (Weirich convention) |
| `@var \|\|= compute` when result can be `nil`/`false` | Use `defined?(@var)` check instead |
| String concatenation with `+=` in loops | Use `<<` or `.join` — `+=` is O(n²) |
| `rescue Exception` | Rescue `StandardError` — `Exception` catches `SignalException`, `NoMemoryError` |
| Deep `&.` chains (3+ links) | Extract to a method or use explicit nil check |
| Missing `# frozen_string_literal: true` | Add to top of every file |

## References

- `references/modern_ruby.md` - Pattern matching, ractors, fiber scheduler, RBS types
- `references/error_handling.md` - Exception hierarchies, result objects, retry patterns
- `references/performance.md` - YJIT, GC tuning, benchmarking, profiling
- `references/ood-philosophy.md` - OOD principles, naming, SOLID, TRUE heuristic, Law of Demeter

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [zarpay](https://github.com/zarpay)
- **Source:** [zarpay/rails-template](https://github.com/zarpay/rails-template)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-zarpay-rails-template-ruby
- Seller: https://agentstack.voostack.com/s/zarpay
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
