Agent skill

Ecto Nested Associations

by j-morgan6 in j-morgan6/elixir-phoenix-guide

A skill your agent uses when a form or operation manages parent and child records together — castassoc/castembed, onreplace, Ecto.Multi across tables, FK cascade design.

MITAuto-check passed

Install Ecto Nested Associations

skills CLI
$ npx skills add j-morgan6/elixir-phoenix-guide --skill ecto-nested-associations -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install j-morgan6/elixir-phoenix-guide ecto-nested-associations --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/j-morgan6/elixir-phoenix-guide.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ecto-nested-associations .claude/skills/ecto-nested-associations && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ecto-nested-associations
GitHub stars
166
Token cost
~2.2k tokens
SKILL.md length
271 words
Files
1
Skills in repo
19
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when a form or operation manages parent and child records together — castassoc/castembed, onreplace, Ecto.Multi across tables, FK cascade design.

  • Works in 6 steps: Use cast_assoc/3 for has_many/has_one —… → Use Ecto.Multi for operations spanning… → Set on_delete explicitly in migrations —… → …
  • Operation manages parent and child records together — castassoc/castembed
  • SKILL.md covers RULES — Follow these with no…, cast_assoc for Nested Creates, cast_assoc for Updates with… and cast_embed for Embedded Schemas, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Ecto Nested Associations is an agent skill from j-morgan6/elixir-phoenix-guide. Use when a form or operation manages parent and child records together — castassoc/castembed, onreplace, Ecto.Multi across tables, FK cascade design.

Its SKILL.md is about 2.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

The licence is MIT.

When your agent uses it

  • Operation manages parent and child records together — castassoc/castembed
  • Ecto.Multi across tables
  • FK cascade design

Example prompts

  • “/ecto-nested-associations”

Workflow steps

6 steps, taken from the first numbered list in SKILL.md.

  1. Use cast_assoc/3 for has_many/has_one — never manually insert children in a separate step; let Ecto manage the relationship
  2. Use Ecto.Multi for operations spanning multiple unrelated tables — not nested changesets; Multi provides explicit rollback control
  3. Set on_delete explicitly in migrations — :delete_all for owned children, :nothing for references to independent entities
  4. Always create indexes on foreign key columns — missing FK indexes cause slow joins and lookups on the child table
  5. Use on_replace: :delete in cast_assoc for list management — allows removing items by omitting them from the input
  6. Preload associations before updating them — cast_assoc/3 raises (attempting to cast or change association ... that was not loaded) if the…

What it can do on your machine

Read from SKILL.md and the folder at commit cdfddac. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are elixir).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Ecto Nested Associations loads about 2.2k tokens when it runs. Until then it costs about 44 tokens; SKILL.md has 271 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~44
When it runs · the whole SKILL.md, loaded when a task matches
~2.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from j-morgan6/elixir-phoenix-guide at commit cdfddac, republished under its MIT licence (© j-morgan6). 271 words, ~2,236 tokens.

Download SKILL.mdSave it as .claude/skills/ecto-nested-associations/SKILL.md (or your agent's skills folder).
name
ecto-nested-associations
description
Use when a form or operation manages parent and child records together — cast_assoc/cast_embed, on_replace, Ecto.Multi across tables, FK cascade design.
file_patterns
**/schemas/**/*.ex, **/*_schema.ex
auto_suggest
true

Ecto Nested Associations

RULES — Follow these with no exceptions

  1. Use cast_assoc/3 for has_many/has_one — never manually insert children in a separate step; let Ecto manage the relationship
  2. Use Ecto.Multi for operations spanning multiple unrelated tables — not nested changesets; Multi provides explicit rollback control
  3. Set on_delete explicitly in migrations — :delete_all for owned children, :nothing for references to independent entities
  4. Always create indexes on foreign key columns — missing FK indexes cause slow joins and lookups on the child table
  5. Use on_replace: :delete in cast_assoc for list management — allows removing items by omitting them from the input
  6. Preload associations before updating them — cast_assoc/3 raises (attempting to cast or change association ... that was not loaded) if the association isn't preloaded; preload before update

cast_assoc for Nested Creates

Create parent and children in a single operation. Ecto sets foreign keys automatically.

elixir
# Schema definitions
defmodule MyApp.Blog.Post do
  use Ecto.Schema
  import Ecto.Changeset

  schema "posts" do
    field :title, :string
    has_many :comments, MyApp.Blog.Comment

    timestamps()
  end

  def changeset(post, attrs) do
    post
    |> cast(attrs, [:title])
    |> validate_required([:title])
    |> cast_assoc(:comments, with: &MyApp.Blog.Comment.changeset/2)
  end
end

defmodule MyApp.Blog.Comment do
  use Ecto.Schema
  import Ecto.Changeset

  schema "comments" do
    field :body, :string
    belongs_to :post, MyApp.Blog.Post

    timestamps()
  end

  # Do NOT require :post_id — cast_assoc sets it automatically
  def changeset(comment, attrs) do
    comment
    |> cast(attrs, [:body])
    |> validate_required([:body])
  end
end

# Usage — create post with comments in one operation
Blog.create_post(%{
  title: "My Post",
  comments: [
    %{body: "First comment"},
    %{body: "Second comment"}
  ]
})

cast_assoc for Updates with on_replace

When updating a has_many, on_replace: :delete removes children that are omitted from the input.

elixir
defmodule MyApp.Recipes.Recipe do
  schema "recipes" do
    field :name, :string
    has_many :ingredients, MyApp.Recipes.Ingredient, on_replace: :delete

    timestamps()
  end

  def changeset(recipe, attrs) do
    recipe
    |> cast(attrs, [:name])
    |> validate_required([:name])
    |> cast_assoc(:ingredients, with: &MyApp.Recipes.Ingredient.changeset/2)
  end
end

# Update — send the full list; omitted items are deleted
def update_recipe(recipe, attrs) do
  recipe
  |> Repo.preload(:ingredients)  # MUST preload before cast_assoc
  |> Recipe.changeset(attrs)
  |> Repo.update()
end

# Example: recipe has ingredients A, B, C
# Sending %{ingredients: [%{id: a.id, name: "A"}, %{name: "D"}]}
# Result: A is updated, B and C are deleted, D is created
Why Preloading Matters
elixir
# Bad — ingredients not preloaded, cast_assoc can't compare
recipe = Repo.get!(Recipe, id)
Recipe.changeset(recipe, attrs)  # ingredients is %Ecto.Association.NotLoaded{}
|> Repo.update()  # Raises: attempting to cast or change association
                  # `ingredients` from `MyApp.Recipes.Recipe` that was not loaded

# Good — preload before updating
recipe = Repo.get!(Recipe, id) |> Repo.preload(:ingredients)
Recipe.changeset(recipe, attrs)  # ingredients is [%Ingredient{}, ...]
|> Repo.update()  # Correctly diffs and applies changes

cast_embed for Embedded Schemas

Use cast_embed for data stored as JSON in a single column (no separate table).

elixir
defmodule MyApp.Profiles.Profile do
  use Ecto.Schema
  import Ecto.Changeset

  schema "profiles" do
    field :name, :string
    embeds_many :social_links, SocialLink, on_replace: :delete

    timestamps()
  end

  def changeset(profile, attrs) do
    profile
    |> cast(attrs, [:name])
    |> cast_embed(:social_links, with: &SocialLink.changeset/2)
  end
end

defmodule MyApp.Profiles.Profile.SocialLink do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key false
  embedded_schema do
    field :platform, :string
    field :url, :string
  end

  def changeset(link, attrs) do
    link
    |> cast(attrs, [:platform, :url])
    |> validate_required([:platform, :url])
    |> validate_format(:url, ~r/^https?:\/\//)
  end
end

Ecto.Multi for Multi-Table Operations

When operations span unrelated tables or need explicit control over transaction steps:

elixir
defmodule MyApp.Orders do
  alias Ecto.Multi

  def place_order(user, cart_items) do
    Multi.new()
    |> Multi.insert(:order, build_order(user))
    |> Multi.insert_all(:line_items, LineItem, fn %{order: order} ->
      Enum.map(cart_items, fn item ->
        %{
          order_id: order.id,
          product_id: item.product_id,
          quantity: item.quantity,
          price: item.price,
          # default timestamps() are :naive_datetime — use DateTime only if
          # the schema uses :utc_datetime
          inserted_at: NaiveDateTime.utc_now(:second),
          updated_at: NaiveDateTime.utc_now(:second)
        }
      end)
    end)
    |> Multi.update(:decrement_stock, fn %{order: _order} ->
      decrement_stock_changeset(cart_items)
    end)
    |> Repo.transaction()
  end
end

# Handling Multi results
case Orders.place_order(user, cart_items) do
  {:ok, %{order: order, line_items: {count, _}, decrement_stock: _}} ->
    # All operations succeeded
    {:ok, order}

  {:error, :order, changeset, _changes_so_far} ->
    # Order insert failed — nothing committed
    {:error, changeset}

  {:error, :decrement_stock, changeset, _changes_so_far} ->
    # Stock update failed — order and line items rolled back
    {:error, changeset}
end
Multi with Run for Custom Logic
elixir
Multi.new()
|> Multi.run(:validate_stock, fn _repo, _changes ->
  if sufficient_stock?(cart_items) do
    {:ok, :valid}
  else
    {:error, :insufficient_stock}
  end
end)
|> Multi.insert(:order, fn %{validate_stock: :valid} ->
  build_order(user)
end)
|> Repo.transaction()

Migration Patterns for Associations

Foreign Keys with Cascade
elixir
defmodule MyApp.Repo.Migrations.CreateComments do
  use Ecto.Migration

  def change do
    create table(:comments) do
      add :body, :text, null: false

      # Child — cascade delete when parent is deleted
      add :post_id, references(:posts, on_delete: :delete_all), null: false

      # Reference — don't cascade (user deletion shouldn't delete comments)
      add :user_id, references(:users, on_delete: :nothing), null: false

      timestamps()
    end

    # Always index foreign keys
    create index(:comments, [:post_id])
    create index(:comments, [:user_id])
  end
end
Cascade Decision Guide
elixir
# :delete_all — child cannot exist without parent
add :comment_id, references(:comments, on_delete: :delete_all)  # Reply → Comment
add :order_id, references(:orders, on_delete: :delete_all), null: false  # LineItem → Order
add :recipe_id, references(:recipes, on_delete: :delete_all), null: false  # Ingredient → Recipe

# :nothing — resource is referenced but independent
add :user_id, references(:users, on_delete: :nothing)  # Post → User
add :category_id, references(:categories, on_delete: :nothing)  # Post → Category

# :nilify_all — remove reference but keep the record
add :team_id, references(:teams, on_delete: :nilify_all)  # User → Team (user keeps account)

Foreign Key Indexes

Every references() column needs an index. Without it, deleting a parent scans the entire child table.

elixir
# Bad — foreign key without index
create table(:comments) do
  add :post_id, references(:posts, on_delete: :delete_all)
end
# Deleting a post requires full table scan of comments to find children

# Good — always add an index
create table(:comments) do
  add :post_id, references(:posts, on_delete: :delete_all)
end
create index(:comments, [:post_id])

Testing Nested Associations

One representative test — assert Ecto.Multi rolls back all steps atomically on failure:

elixir
describe "place_order/2 with Ecto.Multi" do
  test "rolls back on failure" do
    user = user_fixture()
    items = [%{product_id: -1, quantity: 2, price: 999}]

    assert {:error, _step, _changeset, _changes} =
             Orders.place_order(user, items)
  end
end

See ecto-essentials skill for schema and migration fundamentals. See ecto-changeset-patterns skill for changeset composition and validation. See testing-essentials skill for comprehensive testing patterns.

© j-morgan6, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/ecto-nested-associations of j-morgan6/elixir-phoenix-guide.

Open the folder on GitHubat commit cdfddac

Compare with similar skills

Ecto Nested Associations next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Ecto Nested Associations compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Ecto Nested Associations this skillj-morgan6/elixir-phoenix-guide166—~2.2kAutomated safety check: PassMIT
Form Fillingasgeirtj/system_prompts_leaks69k—~400Automated safety check: PassCC0-1.0
Firestore Operations Managerjeremylongshore/tons-of-skills-marketplace2.8k—~728Automated safety check: PassMIT
Carrier Relationship Managementaffaan-m/ECC276k5 repos~5.9kAutomated safety check: PassApache-2.0
Operations Managerborghei/Claude-Skills886—~3.7kAutomated safety check: PassMIT
It Operationsdavila7/claude-code-templates32k1 repos~3.7kAutomated safety check: PassMIT

Similar skills

  • Form Filling

    asgeirtj/system_prompts_leaks

    Fill out online forms (Google Forms, Typeform and similar) or PDF, Word and DocuSign forms; prepare a reviewable draft and get approval before submitting or sending.

    69k GitHub stars~400 tokensUpdated yesterday
    Documents & OfficeAuto-check passed
  • Firestore Operations Manager

    jeremylongshore/tons-of-skills-marketplace

    Manage Firebase/Firestore operations including CRUD, queries, batch processing, and index/rule guidance.

    2.8k GitHub stars~728 tokensUpdated today
    Data & AnalyticsAuto-check passed
  • Supports freight managers in sourcing and vetting carriers, running RFPs, negotiating rates, building routing guides and scoring carrier performance.

    276k GitHub starsUsed in 5 repos~5.9k tokens
    Business, Finance & HRAuto-check passed
  • Operations Manager

    borghei/Claude-Skills

    Operations management across process optimization, efficiency, and continuous improvement.

    886 GitHub stars~3.7k tokensUpdated 2 days ago
    Business, Finance & HRAuto-check passed
  • It Operations

    davila7/claude-code-templates

    Manages IT infrastructure, monitoring, incident response, and service reliability.

    32k GitHub starsUsed in 1 repo~3.7k tokens
    DevOps & CloudAuto-check passed
  • Form Validation

    thedaviddias/Front-End-Checklist

    A skill your agent uses when reviewing templates, rendered HTML, or shared components related to Validate forms accessibly.

    74k GitHub stars~633 tokensUpdated 2 days ago
    Frontend & DesignAuto-check passed

More from j-morgan6/elixir-phoenix-guide

All 19 skills in this repo
  • Code Quality

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when refactoring for duplication, complexity, or dead code — includes the plugin's on-demand analysis scripts.

    166 GitHub stars~1.4k tokensUpdated 3 mo ago
    Auto-check passed
  • Deployment Gotchas

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when preparing releases or deployment config — runtime.exs vs compile-time config, release migrations, PHXHOST/PHXSERVER, assets, health checks.

    166 GitHub stars~2.6k tokensUpdated 3 mo ago
    Auto-check passed
  • Ecto Changeset Patterns

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when a resource needs multiple changesets (registration vs update), conditional validation, field transforms, or uniqueness validation — changeset composition.

    166 GitHub stars~2.1k tokensUpdated 3 mo ago
    Auto-check passed
  • Ecto Essentials

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when defining schemas, writing queries, or creating migrations — schema design, Repo usage, indexes, query composition.

    166 GitHub stars~2.2k tokensUpdated 3 mo ago
    Auto-check passed
  • Elixir Essentials

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when writing or refactoring core Elixir — pattern matching, case/cond/with, pipes, {:ok, }/{:error, } contracts.

    166 GitHub stars~2.2k tokensUpdated 3 mo ago
    Auto-check passed
  • Oban Essentials

    j-morgan6/elixir-phoenix-guide

    A skill your agent uses when writing background jobs with Oban — worker options, return contracts, idempotency, uniqueness, Oban.Testing.

    166 GitHub stars~2.1k tokensUpdated 3 mo ago
    Auto-check passed

Questions about Ecto Nested Associations

What does Ecto Nested Associations do?

A skill your agent uses when a form or operation manages parent and child records together — castassoc/castembed, onreplace, Ecto.Multi across tables, FK cascade design. Ecto Nested Associations is an agent skill from j-morgan6/elixir-phoenix-guide.Multi across tables, FK cascade design.

When should I use Ecto Nested Associations?

Ecto Nested Associations fits situations like: operation manages parent and child records together — castassoc/castembed; ecto.Multi across tables; FK cascade design.

How do I install Ecto Nested Associations in Claude Code?

Run `npx skills add j-morgan6/elixir-phoenix-guide --skill ecto-nested-associations -a claude-code`. Or copy the skill folder (skills/ecto-nested-associations in j-morgan6/elixir-phoenix-guide) into .claude/skills/ecto-nested-associations in your project. Claude Code loads it when a task matches its description.

How do I install Ecto Nested Associations in Codex?

Run `npx skills add j-morgan6/elixir-phoenix-guide --skill ecto-nested-associations -a codex`. Or copy the skill folder (skills/ecto-nested-associations in j-morgan6/elixir-phoenix-guide) into .agents/skills/ecto-nested-associations in your project. Codex loads it when a task matches its description.

Can I use Ecto Nested Associations in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add j-morgan6/elixir-phoenix-guide --skill ecto-nested-associations -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ecto-nested-associations, .gemini/skills/ecto-nested-associations, .github/skills/ecto-nested-associations and .opencode/skills/ecto-nested-associations in your project.

What does Ecto Nested Associations need to run?

SKILL.md names no scripts, command-line tools or credentials: Ecto Nested Associations is instructions for the agent only.

Does Ecto Nested Associations access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Ecto Nested Associations safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Ecto Nested Associations use?

Ecto Nested Associations is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Ecto Nested Associations use?

About 2.2k tokens (SKILL.md is roughly 8.9k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Ecto Nested Associations?

Skills that share tags, products or a category with Ecto Nested Associations: Form Filling (asgeirtj/system_prompts_leaks, 69k stars), Firestore Operations Manager (jeremylongshore/tons-of-skills-marketplace, 2.8k stars), Carrier Relationship Management (affaan-m/ECC, 276k stars) and Operations Manager (borghei/Claude-Skills, 886 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Ecto Nested Associations?

j-morgan6 (a GitHub user) maintains it in j-morgan6/elixir-phoenix-guide, which has 166 GitHub stars. The repository holds 19 skills in this directory. The repository was last updated on July 6, 2026.

Source: j-morgan6/elixir-phoenix-guide on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.