elixir-phoenix-ecto-patterns
Apply Ecto patterns for schemas, changesets, queries, migrations, and preloads.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Apply Ecto patterns for schemas, changesets, queries, migrations, and preloads.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Recommend the right `$elixir-phoenix-*` skill for the current task.
Elixir/Phoenix: Review lifecycle, state-machine, Oban, persistence, pause/resume, retry, and restart-sensitive changes before commit, push, or PR. Use for concurrency-sensitive runtime work to produce explicit blocking vs optional findings, require durability checks, and verify smoke plus restart resilience when applicable.
Capture a solved Phoenix problem as a reusable solution doc.
Audit LiveView assigns for memory bloat, dead assigns, and stream candidates.
Audit project health across architecture, security, performance, tests, and deps.
Analyze Phoenix context boundaries and coupling with `mix xref`.
| name | elixir-phoenix-ecto-patterns |
| description | Apply Ecto patterns for schemas, changesets, queries, migrations, and preloads. |
| metadata | {"short-description":"Apply Ecto schema and query patterns"} |
Reference for working with Ecto schemas, queries, and migrations.
cast/4 for user/API input, change/2 or put_change/3 for internal trusted data:float FOR MONEY — Always use :decimal or :integer (cents)u.name == ^user_input is safe, string interpolation causes SQL injectionhas_many, JOIN FOR belongs_to — Avoids row multiplicationfrom(a in A, b in B) without on: creates Cartesian productcast_assoc WITH SHARED DATA — When multiple parents share child data, deduplicate child records BEFORE building changesets. Dedup only works within a single changesetdefmodule 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
| 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 |
| Relationship | Strategy |
|---|---|
belongs_to | JOIN (single query) |
has_many | Separate queries (avoid row multiplication) |
| 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 |
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