Agent skill
ecto-patterns
Ecto patterns — schemas, changesets, queries, migrations, Multi, associations, preloads, upserts. Use when editing Repo calls, Ecto.Query, or schema fields. Skip for Ash.
Install this agent skill to your Project
npx add-skill https://github.com/oliver-kriska/claude-elixir-phoenix/tree/main/plugins/elixir-phoenix/skills/ecto-patterns
SKILL.md
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
Quick Decisions
cast vs put_change vs change
| Function | Use When |
|---|---|
cast/4 |
External data (user input, API) |
put_change/3 |
Internal trusted data (timestamps, computed) |
change/2 |
Internal data from existing struct |
Preload Strategy
| Relationship | Strategy |
|---|---|
belongs_to |
JOIN (single query) |
has_many |
Separate queries (avoid row multiplication) |
Common Anti-patterns
| Wrong | Right |
|---|---|
field :amount, :float |
field :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 loops | Repo.preload(posts, :comments) |
Repo.get!(User, user_id) with user input |
Repo.get(User, id) + handle nil |
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
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
lab:autoresearch
Self-improving loop for plugin skills. Reads program.md, proposes one mutation per iteration, evaluates against deterministic scorer, keeps improvements via git, reverts failures. Targets weakest skill+dimension. Use with /loop for overnight runs.
promote
Generate X/Twitter release promotion posts with ASCII tables and CodeSnap rendering. Use when writing release posts, promotion tweets, plugin announcements, or preparing social media content for new versions.
skill-monitor
Analyze skill effectiveness across sessions. Computes per-skill metrics (action rate, friction, outcomes), identifies degrading skills, and generates improvement recommendations. Requires session-scan data in metrics.jsonl.
session-trends
Analyze trends across session metrics. Computes windowed aggregates, deltas, and compares against MEMORY.md findings. Use periodically for progress tracking.
cc-changelog
CONTRIBUTOR TOOL - Track CC changelog, extract new versions since last check, analyze impact on plugin (breaking changes, opportunities, deprecations). Run periodically or before releases. NOT part of the distributed plugin.
session-scan
Compute metrics for Claude Code sessions. Discovers via ccrider, filters trivial, computes friction/opportunity/fingerprint scores. Use for broad session triage.
Didn't find tool you were looking for?