mcpField
E
ecto-patterns

ecto-patterns

github.com/oliver-kriska開発57155 回インストール1 週間前に更新
リポジトリ

ecto-patterns について

Ectoのスキーマ、クエリ、マイグレーションを扱う開発者向けのリファレンススキルです。安全なデータ処理やクエリ、プリロード、制約の原則と、よくあるアンチパターンをまとめ、詳細資料も案内します。

主な機能

  1. 01スキーマとチェンジセットの指針
  2. 02安全なクエリとプリロードのパターン
  3. 03マイグレーションと制約の原則
  4. 04よくあるアンチパターンの例

活用シーン

  1. 01castと内部変更関数の選択
  2. 02クエリでのSQLインジェクション回避
  3. 03コレクションのプリロード計画
  4. 04金額フィールドと関連付けの確認

インストール

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

$npx skills add https://github.com/oliver-kriska/claude-elixir-phoenix --skill ecto-patterns

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

同梱ファイル

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

references/
changesets.md
fulltext-search.md
migrations.md
queries.md
transactions.md

詳細

Ecto パターンリファレンス

Ecto のスキーマ、クエリ、マイグレーションを扱うためのリファレンスです。

絶対に守るべき原則 — 違反してはいけません

  1. 変更セットは外部データ用です — ユーザーや API からの入力には cast/4、内部の信頼できるデータには change/2 または put_change/3 を使用します
  2. 金額に :float を使ってはいけません — 常に :decimal または :integer(セント単位)を使用します
  3. Rails 形式のポリモーフィック関連付けは禁止です — 外部キー制約が機能しなくなるため、複数の NULL 許容外部キーまたは個別の結合テーブルを使用します
  4. クエリでは常に値をピン留めします — u.name == ^user_input は安全ですが、文字列補間は SQL インジェクションの原因になります
  5. 個別のレコードではなく、コレクションをプリロードします — ループ内でのプリロードは N+1 クエリを引き起こします
  6. 競合状態にはバリデーションより制約を使います — バリデーションはすばやいフィードバックを提供し、制約はデータベースレベルの安全性を提供します
  7. has_many には個別のクエリ、belongs_to には JOIN を使います — 行の重複を防げます
  8. 暗黙のクロス結合は禁止です — from(a in A, b in B) は on: がない場合、直積を生成します
  9. 共有データで cast_assoc を使う前に重複を除去します — 複数の親が子データを共有する場合、変更セットを作成する前に子レコードの重複を除去します。重複除去が機能するのは、単一の変更セット内だけです

スキーマのクイックテンプレート

defmodule MyApp.Context.Entity do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id

  schema "entities" do
    field :name, :string
    field :status, Ecto.Enum, values: [:draft, :active, :archived]
    field :amount_cents, :integer  # Never :float for money!
    belongs_to :user, MyApp.Accounts.User
    timestamps(type: :utc_datetime_usec)
  end

  def changeset(entity, attrs) do
    entity
    |> cast(attrs, [:name, :status, :amount_cents])
    |> validate_required([:name])
    |> foreign_key_constraint(:user_id)
  end
end

クイック判断ガイド

cast と put_change と change
関数使用する場面
cast/4外部データ(ユーザー入力、API)
put_change/3内部の信頼できるデータ(タイムスタンプ、計算値)
change/2既存の構造体からの内部データ
プリロード戦略
関連付け戦略
belongs_toJOIN(単一クエリ)
has_many個別のクエリ(行の重複を回避)

よくあるアンチパターン

誤り正しい方法
field :amount, :floatfield :amount_cents, :integer
"SELECT * WHERE name = '#{name}'"from(u in User, where: u.name == ^name)
Repo.all(User) |> Enum.filter(& &1.active)from(u in User, where: u.active)
ループ内でプリロードするRepo.preload(posts, :comments)
ユーザー入力を使って Repo.get!(User, user_id) を呼び出すRepo.get(User, id) + nil を処理する
Repo.transaction 内で {:ok, _} = Repo.update(cs) を実行するcase/with + Repo.rollback(cs)(transactions.md を参照)

リファレンス

詳しいパターンについては、以下を参照してください。

  • ${CLAUDE_SKILL_DIR}/references/changesets.md - cast と put_change、カスタムバリデーション、prepare_changes
  • ${CLAUDE_SKILL_DIR}/references/queries.md - 合成可能なクエリ、dynamic、サブクエリ、プリロード
  • ${CLAUDE_SKILL_DIR}/references/migrations.md - 安全なマイグレーション、同時インデックス作成、NOT NULL
  • ${CLAUDE_SKILL_DIR}/references/transactions.md - Repo.transact、Ecto.Multi、アップサート

コメント