
Ecto Patterns
Use when a task touches Ecto, even a how-to question: schemas, changesets, validations...
Install
npx skills add oliver-kriska/claude-elixir-phoenix --skill ecto-patterns -g -a claude-code -y- Repository
- oliver-kriska/claude-elixir-phoenix572
- Category
- Writing
- Updated
- 5d ago
- License
- MIT
- Context cost
- Lightabout 816 tokens
- Runs scripts
- No, instructions only
What it does
Use when a task touches Ecto, even a how-to question: schemas, changesets, validations, queries, preloads, Multi, migrations, constraints, money fields. Load it before writing Ecto code. Skip for Ash.
Ecto Patterns Reference
Reference for working with Ecto schemas, queries, and migrations.
Iron Laws, Never Violate These
- CHANGESETS ARE FOR EXTERNAL DATA, Use
cast/4for user/API input,change/2orput_change/3for internal trusted data - NEVER USE
:floatFOR MONEY, Always use:decimalor:integer(cents) - NO RAILS-STYLE POLYMORPHIC ASSOCIATIONS, They break foreign key constraints; use multiple nullable FKs or separate join tables
- ALWAYS PIN VALUES IN QUERIES,
u.name == ^user_inputis safe, string interpolation causes SQL injection - PRELOAD COLLECTIONS, NOT INDIVIDUALS, Preloading in loops = N+1 queries
- CONSTRAINTS BEAT VALIDATIONS FOR RACE CONDITIONS, Validations provide quick feedback, constraints provide DB-level safety
- SEPARATE QUERIES FOR
has_many, JOIN FORbelongs_to, Avoids row multiplication - NO IMPLICIT CROSS JOINS,
from(a in A, b in B)withouton:creates Cartesian product - DEDUP BEFORE
cast_assocWITH 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
