mcpField
R
ruby

ruby

github.com/midudev開発7.0k56 回インストール2 週間前に更新
リポジトリ

ruby について

Ruby 3.x 以降の慣用表現と規約を示すスキルです。開発者やコーディングエージェント向けに、エラー処理、現代的な言語機能、性能、コード構成を解説します。

主な機能

  1. 01例外と結果オブジェクトのパターン
  2. 02Ruby 3.x の言語機能
  3. 03性能を考慮した列挙処理
  4. 04安全なメモ化と文字列構築
  5. 05メソッド順序とファイル構成

活用シーン

  1. 01想定内の失敗に対する規約の選択
  2. 02現代的な Ruby 構文とパターンの適用
  3. 03列挙処理と文字列構築の効率化
  4. 04Ruby クラス内のメソッド整理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/midudev/autoskills --skill ruby

インストール後、Claude Code で/rubyを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
error_handling.md
method_ordering.md
modern_ruby.md
ood-philosophy.md
performance.md

詳細

Ruby 言語スキル

概要

慣用的な Ruby 3.x 以降のコードを書くための、独自の Ruby 規約とイディオムです。エージェントがデフォルトでは見落としがちなパターン、つまり Weirich の raise/fail の使い分け、nil を考慮した安全なメモ化、想定される失敗に対する例外よりも結果オブジェクトを使う方法、パフォーマンスを意識した列挙に重点を置いています。

エラー処理の規約

Weirich の raise/fail 規約

初回の例外には fail を使い、再送出に限り raise を使います。

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
カスタム例外階層

ドメイン例外は基底エラーの下にまとめます。

module MyApp
  class Error < StandardError; end
  class PaymentError < Error; end
  class InsufficientFundsError < PaymentError; end
end

# Rescue at any granularity:
rescue MyApp::InsufficientFundsError  # specific
rescue MyApp::PaymentError            # category
rescue MyApp::Error                   # all app errors
想定される失敗に対する結果オブジェクト

想定される失敗経路には、例外ではなく結果オブジェクトを使います。

class Result
  attr_reader :value, :error
  def self.success(value) = new(value: value)
  def self.failure(error) = new(error: error)
  def initialize(value: nil, error: nil) = (@value, @error = value, error)
  def success? = error.nil?
  def failure? = !success?
end
呼び出し元が指定するフォールバック

ブロックを使って、呼び出し元がエラー処理を定義できるようにします。

def fetch_user(id, &fallback)
  User.find(id)
rescue ActiveRecord::RecordNotFound => e
  fallback ? fallback.call(e) : raise
end

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

詳しいパターンとリトライ戦略については、references/error_handling.md を参照してください。

モダン Ruby(3.x 以降)

パターンマッチング
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
その他の 3.x 以降の機能
# 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}

Ractor、ファイバースケジューラー、RBS 型、応用的なパターンマッチングについては、references/modern_ruby.md を参照してください。

すぐにできるパフォーマンス改善

文字列リテラルの凍結
# frozen_string_literal: true
# Add to top of every file. Prevents mutation, reduces allocations.
# When you need mutable: String.new("hello") or +"hello"
効率的な列挙
# 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)
nil/false に関する注意を踏まえたメモ化
# 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
文字列の構築
# 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

YJIT、GC のチューニング、ベンチマーク、プロファイリングツールについては、references/performance.md を参照してください。

推奨する Ruby のイディオム

ガード節
def process(value)
  return unless value
  return unless value.valid?
  # main logic here
end
配列リテラルコンストラクター
STATES = %w[draft published archived]      # word array
FIELDS = %i[name email created_at]         # symbol array
必須キーには Hash#fetch
config.fetch(:api_key)                     # raises KeyError if missing
config.fetch(:timeout, 30)                 # default value
config.fetch(:handler) { build_handler }   # lazy default
セーフナビゲーション
user&.profile&.avatar_url  # returns nil if any link is nil
述語メソッドと bang メソッドの規約
  • ? 接尾辞:真偽値を返します(empty?、valid?、admin?)
  • ! 接尾辞:危険なバージョンです。レシーバーを変更するか、失敗時に例外を発生させます(save!、sort!)
  • bang メソッドを定義する場合は、必ず bang なしの代替メソッドも用意します

メソッドの順序とファイル構成

クラスは、読者が一度に 1 段階ずつ抽象度を下げながら読み進められるよう、上から下へと構成します。これは「ステップダウン」/新聞記事型レイアウトと呼ばれます。要素の順序は次のとおりです。

  1. extend/include/prepend
  2. 定数
  3. attr_* のリーダー/ライターとクラスマクロ(has_many、validates、scope)
  4. def initialize
  5. パブリックメソッド — 抽象度の高いエントリーポイントから順に並べます
  6. protected
  7. private ヘルパー — 抽象度ごとにまとめます

パブリックブロック内とプライベートブロック内では、呼び出し元をたどる深さ優先ではなく、抽象度に応じて幅優先に並べます。 同じ抽象度のメソッドを隣り合わせにし、その後にそれらが呼び出すヘルパー、さらにそのヘルパーが呼び出すヘルパーを並べます。唯一の呼び出し元の直下にヘルパーを定義すると、高レベルの手順が分散し、詳細に埋もれてしまいます。

# Good — breadth-first by altitude: stages cluster, then their helpers
def process; validate; charge; notify; end   # altitude 1 (public entry)

private

def validate; end                            # altitude 2: stages together
def charge;   end
def notify;   end

def verify_customer; end                      # altitude 3: helpers together
def submit_payment;  end
def write_audit_log; end

# Bad — depth-first by caller: altitudes 2 and 3 interleave, stages scatter
def validate;        end
def verify_customer; end
def charge;          end
def submit_payment;  end
def notify;          end
def write_audit_log; end

具体例、ステップダウン/SLAP の背景、共通ヘルパーの配置については、references/method_ordering.md を参照してください。

よくある間違い

間違い修正
新しい例外に raise を使うfail を使い、raise は再送出用にします(Weirich 規約)
結果が nil/false になる可能性があるときに @var ||= compute を使う代わりに defined?(@var) で確認します
ループ内で += による文字列連結を行う<< または .join を使います — += は O(n²) です
rescue ExceptionStandardError を rescue します — Exception は SignalException や NoMemoryError も捕捉します
&. を 3 回以上連鎖させるメソッドに切り出すか、明示的な nil チェックを使います
# frozen_string_literal: true がないすべてのファイルの先頭に追加します
唯一の呼び出し元の直下にヘルパーを定義する(深さ優先)メソッドを抽象度ごとにまとめ、幅優先のレイアウトにします(ステップダウン規則)

参考資料

  • references/modern_ruby.md - パターンマッチング、Ractor、ファイバースケジューラー、RBS 型
  • references/error_handling.md - 例外階層、結果オブジェクト、リトライパターン
  • references/performance.md - YJIT、GC のチューニング、ベンチマーク、プロファイリング
  • references/ood-philosophy.md - OOD の原則、命名、SOLID、TRUE ヒューリスティック、デメテルの法則
  • references/method_ordering.md - ファイル構成の順序、ステップダウン規則、幅優先と深さ優先のメソッド順序

コメント