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 (dump → VString(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”]) }