mcpField
R
rails-refactorer

rails-refactorer

github.com/majesticlabs-dev開発5053 回インストール7 週間前に更新
リポジトリ

rails-refactorer について

rails-refactorerは、Railsの規約、Rubyの慣用表現、Sandi Metzのルールに沿ったリファクタリングのスキルガイドです。テストの維持や本番環境で安全なマイグレーションも扱い、変更内容の報告形式も定めています。

主な機能

  1. 01変更前のコードとテストの分析
  2. 02Railsのコントローラーとモデルの規約
  3. 03Sandi MetzのルールとRubyの慣用表現
  4. 04リファクタリング中のテストカバレッジ維持
  5. 05マイグレーションの安全性と可逆性の確認
  6. 06変更、テスト状況、警告の報告

活用シーン

  1. 01Railsのコントローラーやモデルのリファクタリング
  2. 02複雑なサービス処理の分割
  3. 03データ損失やロックのリスクを伴うマイグレーションの確認

インストール

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

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill rails-refactorer

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

詳細

Rails リファクタラー

リファクタリングの進め方

1. 変更前に分析する

リファクタリングを行う前に:

  • 既存のコードを十分に読みます
  • 既存のテストカバレッジ(spec/ または test/)を確認します
  • コードの目的と背景を理解します
  • コードベース内の既存のパターンを確認します
2. Rails の規約を適用する

コントローラー:

  • コントローラーは薄く保ちます(オーケストレーションのみ)
  • 共通のセットアップには before_action を使います
  • RESTful アクションは 7 つまでに制限し、カスタムアクションには新しいコントローラーを作成します
  • ストロングパラメーターを使います
# Before: Custom action
class MessagesController < ApplicationController
  def archive
    @message = Message.find(params[:id])
    @message.update(archived: true)
  end
end

# After: Dedicated controller
class Messages::ArchivesController < ApplicationController
  def create
    @message = Message.find(params[:message_id])
    @message.update(archived: true)
  end
end

モデル:

  • ビジネスロジックはモデルに記述します
  • 共通の振る舞いには concern を使います
  • よく使うクエリにはスコープを使います
  • 意味が分かりやすい関連名を付けます
# Before
belongs_to :user

# After
belongs_to :author, class_name: "User"

サービスオブジェクト(適切な場合):

  • 複雑な複数ステップの処理に使います
  • 複数のモデルにまたがる処理に使います
  • 単一の目的に絞ります
3. Sandi Metz のルールを適用する
ルール上限対応
クラスの行数100 行クラスを抽出する
メソッドの行数5 行メソッドを抽出する
パラメーター数最大 4 個パラメーターオブジェクトを使う
コントローラーオブジェクト数1 個ファサードを使う
4. 慣用的な Ruby

推奨:

# Guard clauses
return unless user.active?

# Semantic methods
items.any?
email.present?

# Symbol to proc
users.map(&:name)

# Hash shorthand (Ruby 3.x)
{ name:, email: }

避けること:

# Nested conditionals
if user
  if user.active?
    # ...
  end
end

# Manual checks
items.length > 0
email != nil && email != ""
5. テストカバレッジを維持する
  • リファクタリングの前後にテストを実行します
  • インターフェースが変わる場合はテストを更新します
  • 抽出したクラスやメソッドのテストを追加します
  • 既存のテストを決して失敗させません

マイグレーションの安全性

リファクタリングにマイグレーションが含まれる場合は、本番環境での安全性、データの保持、可逆性を確認します。

安全性を確保するツール

推奨 gem:

# Gemfile
gem "strong_migrations"      # Catches dangerous operations
gem "database_consistency"   # Validates model <-> DB constraints
gem "anchor_migrations"      # DDL lock timeout protection
可逆性
# PROBLEM: Irreversible migration
def change
  remove_column :users, :legacy_id
end

# SOLUTION: Explicit up/down with data preservation
def up
  execute "CREATE TABLE legacy_user_ids AS SELECT id, legacy_id FROM users"
  remove_column :users, :legacy_id
end

def down
  add_column :users, :legacy_id, :integer
  execute "UPDATE users SET legacy_id = (SELECT legacy_id FROM legacy_user_ids WHERE legacy_user_ids.id = users.id)"
end
安全なカラム操作
# PROBLEM: Adding NOT NULL locks table
add_column :users, :status, :string, null: false

# SOLUTION: Three-step migration
add_column :users, :status, :string
User.update_all(status: 'active')
change_column_null :users, :status, false
時間のかかる操作
# PROBLEM: Locks table during index creation
add_index :orders, :customer_id

# SOLUTION: Concurrent index (PostgreSQL)
disable_ddl_transaction!
add_index :orders, :customer_id, algorithm: :concurrently
データ損失のシナリオ
操作リスク安全な代替策
カラムの型を変更する切り捨て新しいカラムを追加し、データを移行してから古いカラムを削除する
カラムを削除するデータ損失先にアーカイブしてから削除する
カラム名を変更するアプリのエラー追加し、データをバックフィルしてから削除する
精度を変更するデータ損失拡張のみとし、縮小しない
マイグレーションレビューのチェックリスト
  • マイグレーションは可逆ですか? または明示的な down がありますか?
  • 破壊的な変更の前にデータは保持されていますか?
  • 時間のかかる操作では algorithm: :concurrently を使っていますか?
  • NOT NULL は安全に追加されていますか(nullable -> backfill -> constrain)?
  • strong_migrations は成功していますか?
  • DDL のロックタイムアウトは設定されていますか?

出力形式

リファクタリング後、次の内容を提示します:

  1. 概要 - リファクタリングした内容とその理由
  2. 変更点 - 主な変更内容を含む変更ファイル
  3. テスト状況 - テストが引き続き成功していることの確認
  4. 警告 - 潜在的な問題や必要なフォローアップ

コメント