update!() { /* proc-macro */ }Expand description
Expands struct-literal syntax into update-builder method chains. Returns
the same builder target.update() would return — call
.exec(&mut db).await? to execute the update.
§Syntax
toasty::update!(target { field: value, ... })target is any expression that has an .update() method — a model
instance, a query builder, or a scoped relation accessor.
// Instance target
toasty::update!(user { name: "Alice Smith" })
.exec(&mut db).await?;
// Query target
toasty::update!(User::filter_by_id(id) { name: "Bob" })
.exec(&mut db).await?;Instance targets do not consume the binding — the macro expands to
user.update(), which auto-borrows &mut user the same way the
chain form does. user stays owned after the macro returns.
Value expressions are evaluated before the target is borrowed, so they may read the target’s own fields:
toasty::update!(todo { done: !todo.done }).exec(&mut db).await?;§Field shapes
§Explicit
field: expr sets the field to expr:
toasty::update!(user {
name: "Alice Smith",
email: "alice.smith@example.com",
}).exec(&mut db).await?;expr is any Rust expression. For collection fields, pass a
toasty::stmt::* combinator (e.g. stmt::push("x"),
stmt::apply([...])) for non-set semantics.
§Shorthand
field alone is equivalent to field: field, matching Rust struct
literal shorthand:
let name = "Alice Smith";
toasty::update!(user { name }).exec(&mut db).await?;§Method shorthand
field.combinator(args) is shorthand for
field: toasty::stmt::combinator(args). Any function in toasty::stmt
works; missing functions surface as ordinary “no function” errors:
// tags.push("rust") expands to tags: stmt::push("rust")
toasty::update!(article { tags.push("rust") })
.exec(&mut db).await?;The shorthand is one method call deep. For chained expressions, use
the explicit field: expr form.
§Embedded patch
field: { sub: val, ... } partially updates an embedded struct
field, leaving sub-fields not listed unchanged. Expands to
stmt::apply([stmt::patch(...), ...]):
toasty::update!(doc {
meta: { version: 2, status: "published" },
}).exec(&mut db).await?;Sub-fields nest to arbitrary depth. To replace an embedded value
wholesale, pass the typed value directly: meta: Metadata { ... }.
§Has-many insert
field: [{ ... }, ...] inserts new children of a has-many relation.
Each { ... } becomes a create builder wrapped in
stmt::insert(...); the whole list is wrapped in
stmt::apply([...]):
toasty::update!(user {
todos: [{ title: "buy milk" }, { title: "walk dog" }],
}).exec(&mut db).await?;Items can also be plain expressions, mixed in with builder shorthands — useful for combining inserts and removals:
toasty::update!(user {
todos: [{ title: "new" }, toasty::stmt::remove(&old)],
}).exec(&mut db).await?;§Field validation
The macro emits a method call per named field on the update builder. A field name the model does not expose for update fails with the compiler’s standard “no method named …” error at the macro call site.