Use when Elixir Ecto patterns including schemas, changesets, queries, and transactions. Use when building database-driven Elixir applications.
View on GitHubTheBushidoCollective/han
jutsu-elixir
January 24, 2026
Select agents to install to:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-elixir/skills/elixir-ecto-patterns/SKILL.md -a claude-code --skill elixir-ecto-patternsInstallation paths:
.claude/skills/elixir-ecto-patterns/# Elixir Ecto Patterns
Master Ecto, Elixir's database wrapper and query generator. This skill
covers schemas, changesets, queries, associations, and transactions for
building robust database applications.
## Schema Definition
```elixir
defmodule MyApp.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :name, :string
field :email, :string
field :age, :integer
field :is_active, :boolean, default: true
field :role, Ecto.Enum, values: [:user, :admin, :moderator]
has_many :posts, MyApp.Post
belongs_to :organization, MyApp.Organization
timestamps()
end
def changeset(user, attrs) do
user
|> cast(attrs, [:name, :email, :age, :is_active, :role])
|> validate_required([:name, :email])
|> validate_format(:email, ~r/@/)
|> validate_number(:age, greater_than: 0, less_than: 150)
|> unique_constraint(:email)
end
end
```
## Changeset Validations
```elixir
defmodule MyApp.Post do
use Ecto.Schema
import Ecto.Changeset
schema "posts" do
field :title, :string
field :body, :text
field :published, :boolean, default: false
field :tags, {:array, :string}, default: []
belongs_to :user, MyApp.User
timestamps()
end
def changeset(post, attrs) do
post
|> cast(attrs, [:title, :body, :published, :tags, :user_id])
|> validate_required([:title, :body, :user_id])
|> validate_length(:title, min: 3, max: 100)
|> validate_length(:body, min: 10)
|> foreign_key_constraint(:user_id)
end
def publish_changeset(post) do
post
|> change(published: true)
end
end
```
## Basic Queries
```elixir
import Ecto.Query
# Get all users
Repo.all(User)
# Get user by ID
Repo.get(User, 1)
Repo.get!(User, 1) # Raises if not found
# Get by specific field
Repo.get_by(User, email: "user@example.com")
# Filter with where clause
query = from u in User, where: u.age > 18
Repo.all(query)
# Select specific fields
query = from u in User, select: {u.id, u.nam