mcpField
E
ecto-patterns

ecto-patterns

github.com/oliver-kriskaDevelopment57155 installsUpdated 1w ago
Repository

About ecto-patterns

A reference skill for developers working with Ecto schemas, queries, and migrations. It summarizes safe data handling, query and preload choices, database constraints, and common anti-patterns, with links to detailed references.

Key features

  1. 01Schema and changeset guidance
  2. 02Safe query and preload patterns
  3. 03Migration and constraint principles
  4. 04Examples of common anti-patterns

Use cases

  1. 01Choose cast or internal change functions
  2. 02Avoid SQL injection in queries
  3. 03Plan collection preloading
  4. 04Review money fields and associations

Install

Copy the command and run it in a terminal.

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

After installing, type/ecto-patternsin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

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

Details

From the project README

Ecto Patterns Reference

Reference for working with Ecto schemas, queries, and migrations.

Iron Laws — Never Violate These

  1. CHANGESETS ARE FOR EXTERNAL DATA — Use cast/4 for user/API input, change/2 or put_change/3 for internal trusted data
  2. NEVER USE :float FOR MONEY — Always use :decimal or :integer (cents)
  3. NO RAILS-STYLE POLYMORPHIC ASSOCIATIONS — They break foreign key constraints; use multiple nullable FKs or separate join tables
  4. ALWAYS PIN VALUES IN QUERIES — u.name == ^user_input is safe, string interpolation causes SQL injection
  5. PRELOAD COLLECTIONS, NOT INDIVIDUALS — Preloading in loops = N+1 queries
  6. CONSTRAINTS BEAT VALIDATIONS FOR RACE CONDITIONS — Validations provide quick feedback, constraints provide DB-level safety
  7. SEPARATE QUERIES FOR has_many, JOIN FOR belongs_to — Avoids row multiplication
  8. NO IMPLICIT CROSS JOINS — from(a in A, b in B) without on: creates Cartesian product
  9. DEDUP BEFORE cast_assoc WITH SHARED DATA — When multiple parents share child data, deduplicate child records BEFORE building changesets. Dedup only works within a single changeset

Quick Schema Template

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

Quick Decisions

cast vs put_change vs change
FunctionUse When
cast/4External data (user input, API)
put_change/3Internal trusted data (timestamps, computed)
change/2Internal data from existing struct
Preload Strategy
RelationshipStrategy
belongs_toJOIN (single query)
has_manySeparate queries (avoid row multiplication)

Common Anti-patterns

WrongRight
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)
Preloading in loopsRepo.preload(posts, :comments)
Repo.get!(User, user_id) with user inputRepo.get(User, id) + handle nil
{:ok, _} = Repo.update(cs) inside Repo.transactioncase/with + Repo.rollback(cs) (see transactions.md)

References

For detailed patterns, see:

  • ${CLAUDE_SKILL_DIR}/references/changesets.md - cast vs put_change, custom validations, prepare_changes
  • ${CLAUDE_SKILL_DIR}/references/queries.md - Composable queries, dynamic, subqueries, preloading
  • ${CLAUDE_SKILL_DIR}/references/migrations.md - Safe migrations, concurrent indexes, NOT NULL
  • ${CLAUDE_SKILL_DIR}/references/transactions.md - Repo.transact, Ecto.Multi, upserts

Comments

Markdown supported