lode/embed

Embedded schemas — embeds_one / embeds_many + cast_embed.

An embed is a nested schema stored inline as a single jsonb column, not in a separate table. The embeds_one/embeds_many constructors return an LodeType you put on a parent field with schema.field; it bridges the child Schema and a JSON-text Value (dumpVString(json), load → parse → child record).

cast_embed_one/cast_embed_many mirror changeset.cast_assoc, but because embeds live inline they write the encoded JSON straight into the parent’s changes — there is no separate repo write (contrast put_assoc).

Types

What to do with existing embeds absent from the new params (Ecto’s embed on_replace). EmbedDelete drops them (the inline default — they simply leave the stored JSON); EmbedRaise invalidates the parent if any existing embed would be silently dropped.

pub type EmbedReplace {
  EmbedDelete
  EmbedRaise
}

Constructors

  • EmbedDelete
  • EmbedRaise

Values

pub fn cast_embed_many(
  changeset cs: changeset.Changeset(parent),
  name name: String,
  data data: child,
  params params: List(dict.Dict(String, value.Value)),
  with with: fn(child, dict.Dict(String, value.Value)) -> changeset.Changeset(
    child,
  ),
) -> changeset.Changeset(parent)

Cast a list of param maps into embedded changesets and store them inline (Ecto’s cast_embed for embeds_many). If any child is invalid the parent is marked invalid.

pub fn cast_embed_many_by_key(
  changeset cs: changeset.Changeset(parent),
  name name: String,
  existing existing: List(child),
  blank blank: child,
  params params: List(dict.Dict(String, value.Value)),
  key_param key_param: String,
  child_key child_key: fn(child) -> value.Value,
  on_replace on_replace: EmbedReplace,
  with with: fn(child, dict.Dict(String, value.Value)) -> changeset.Changeset(
    child,
  ),
) -> changeset.Changeset(parent)

cast_embed_many with identity-based matching (Ecto’s embed identity): each param matches an existing embed by key_param (e.g. an "id") — a match casts that embed (an update preserving its other fields, including the id), a non-match casts blank (a new embed). Existing embeds matched by no param follow on_replace. Stamp new embeds with an id beforehand using put_new_id in your with cast, so updates can find them next time.

pub fn cast_embed_one(
  changeset cs: changeset.Changeset(parent),
  name name: String,
  data data: child,
  params params: dict.Dict(String, value.Value),
  with with: fn(child, dict.Dict(String, value.Value)) -> changeset.Changeset(
    child,
  ),
) -> changeset.Changeset(parent)

Cast params into a single embedded changeset and store the result inline on the parent (Ecto’s cast_embed for embeds_one). with turns the params into the child changeset (typically a changeset.cast). If the child is invalid the parent is marked invalid.

pub fn embeds_many(
  related related: fn() -> schema.Schema(child),
) -> type_.LodeType(List(child))

A list of embedded records (embeds_many).

pub fn embeds_one(
  related related: fn() -> schema.Schema(child),
) -> type_.LodeType(child)

A single embedded record (embeds_one). related is a thunk returning the child schema (a thunk to allow mutually-recursive schema definitions).

pub fn put_new_id(
  params params: dict.Dict(String, value.Value),
  field field: String,
) -> dict.Dict(String, value.Value)

Stamp a freshly generated v4 UUID into field of a param map if it is absent — the autogenerated embed id (Ecto’s embed binary_id). Apply it in a cast_embed_many_by_key with callback so new embeds get a stable identity:

with: fn(c, p) { changeset.cast(c, item_schema(), embed.put_new_id(p, “id”), [“id”, “name”]) }

Search Document