ecto-patterns
Ecto patterns — schemas, changesets, queries, migrations, Multi; Use
它会碰到什么
这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。
技能内容
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 |
| {:ok, _} = Repo.update(cs) inside Repo.transaction | case/with + Repo.rollback(cs) (see transactions.md) |
References
For detailed patterns, see:
references/changesets.md- cast vs put_change, custom validations, prepare_changesreferences/queries.md- Composable queries, dynamic, subqueries, preloadingreferences/migrations.md- Safe migrations, concurrent indexes, NOT NULLreferences/transactions.md- Repo.transact, Ecto.Multi, upserts
想直接用这个技能?
本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。
它属于哪个仓库
targets/codex/skills/ecto-patterns/SKILL.md同一个仓库里的其他技能
同名技能的其他版本
有 6 个不同仓库或目录里都有叫 ecto-patterns 的技能。它们内容并不相同,别混用:
- oliver-kriska/claude-elixir-phoenix — Ecto patterns — schemas, changesets, queries, migrations, Multi, associations, preloads, u
- oliver-kriska/claude-elixir-phoenix — Ecto patterns — schemas, changesets, queries, migrations, Multi, associations,
- oliver-kriska/claude-elixir-phoenix — Ecto patterns — schemas, changesets, queries, migrations, Multi, associations,
- oliver-kriska/claude-elixir-phoenix — Ecto patterns — schemas, changesets, queries, migrations, Multi, associations,
- oliver-kriska/claude-elixir-phoenix — Ecto patterns — schemas, changesets, queries, migrations, Multi, associations,