ecto-constraint-debug について
ecto-constraint-debugは、Ectoの制約エラーを調査するElixir開発者向けのデバッグスキルです。エラーの制約名から移行、スキーマの処理、すべての書き込み経路を確認し、競合状態の可能性も調べます。
主な機能
- 01制約エラーの詳細を読み取る
- 02マイグレーションとスキーマ制約を照合
- 03挿入・更新経路を追跡
- 04競合状態の可能性を調査
- 05制約の種類に応じた修正方法
活用シーン
- 01一意制約違反の診断
- 02外部キーエラーの原因特定
- 03Changesetの制約エラーの調査
- 04検証通過後に発生する並行書き込みの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ oliver-kriska/ claude-elixir-phoenix --skill ecto-constraint-debugインストール後、Claude Code で/ecto-constraint-debugを入力して読み込まれたか確認します。
同梱ファイルreferences/constraint-patterns.md
詳細
Ecto 制約のデバッグ
Ash プロジェクト:Ash は独自のエラー DSL を通じて DB 制約を表面化します。
ash-frameworkスキルを使用してください —mix usage_rules.search_docs "constraint" -p ash_postgres。
制約違反を診断するための体系的なアプローチです。Ecto.ConstraintError、unique_constraint、foreign_key_constraint、または制約関連の changeset エラーが発生したときに読み込んでください。
鉄則
- 制約名を読む — 制約名(例:
links_url_index)から、失敗したインデックス/制約を正確に特定できます。まずエラーメッセージから読み取ってください - コードより先にマイグレーションを確認する —
priv/repo/migrations/の制約定義がスキーマの想定と一致することを確認してください - すべての挿入経路をたどる — 制約対象のテーブルに挿入するコード経路をすべて見つけてください。バグは、考慮していなかった経路に潜んでいることがよくあります
- 証明されるまでは競合状態を疑う — バリデーションが通過しても制約違反が発生する場合は、単一リクエストが原因だと証明できるまでは、同時挿入を想定してください
ステップごとのデバッグ
ステップ 1:エラーを読み取る
エラーメッセージから次の情報を抽出します:
- 制約名(例:
users_email_index) - テーブル名(例:
users) - 操作(挿入、更新、削除)
- 競合する値(ログに記録されている場合)
ステップ 2:マイグレーションを見つける
Grep を使って priv/repo/migrations/ 内の制約名を検索します。また、create unique_index、create index、add constraint も確認してください。
確認事項:マイグレーションの制約は、スキーマの unique_constraint/3 または foreign_key_constraint/3 の呼び出しと一致していますか?
ステップ 3:スキーマを見つける
Grep を使って、lib/ 内の changeset における制約処理(unique_constraint、foreign_key_constraint、check_constraint)を見つけます。
ステップ 4:挿入経路をたどる
このスキーマを挿入/更新する呼び出し元をすべて見つけます:
Grep を使って、lib/ 内のすべての挿入/更新経路(Repo.insert、Repo.update、Repo.insert_all、cast_assoc)を見つけます。
ステップ 5:原因を特定する
| 症状 | 考えられる原因 | 修正パターン |
|---|---|---|
| 同じユーザーが 2 回処理を実行する | 競合状態(二重クリック、再試行) | on_conflict を使った Upsert |
| 複数の親が子を共有する | cast_assoc は changeset 間で重複を排除しない | changeset を作成する前に重複を排除する |
| API リクエストが同時に実行される | トランザクション分離の不足 | Repo.transaction で囲むか、upsert を使う |
| 既存データに対して制約を追加するマイグレーション | データが新しい制約に違反している | 事前にデータをバックフィルするか、クリーンアップする |
ステップ 6:修正を適用する
詳しい修正パターンについては、${CLAUDE_SKILL_DIR}/references/constraint-patterns.md を参照してください。
制約の種類ごとのクイック修正
一意性違反 → Upsert:Repo.insert(changeset, on_conflict: :replace_all, conflict_target: [:field])
外部キー違反 → 確認:参照先のレコードは存在していますか? 同時に削除されていませんか?
チェック制約 → 検証:値は制約条件を満たしていますか?
参考資料
${CLAUDE_SKILL_DIR}/references/constraint-patterns.md- 各制約タイプの詳しいパターン