create!() { /* proc-macro */ }Expand description
Expands struct-literal syntax into create builder method chains. Returns one
or more create builders — call .exec(&mut db).await? to insert the
record(s).
§Syntax forms
§Single creation
toasty::create!(Type { field: value, ... })Expands to Type::create().field(value)... and returns the model’s create
builder (e.g., UserCreate).
let user = toasty::create!(User {
name: "Alice",
email: "alice@example.com"
})
.exec(&mut db)
.await?;§Scoped creation
toasty::create!(in expr { field: value, ... })Expands to expr.create().field(value).... Creates a record through a
relation accessor. The foreign key is set automatically.
let todo = toasty::create!(in user.todos() { title: "buy milk" })
.exec(&mut db)
.await?;
// todo.user_id == user.id§Typed batch
toasty::create!(Type::[ { fields }, { fields }, ... ])Expands to a tuple of create builders. Pass the result to
[toasty::batch()] to execute:
let (alice, bob) = toasty::batch(toasty::create!(User::[
{ name: "Alice" },
{ name: "Bob" },
]))
.exec(&mut db)
.await?;§Mixed batch
toasty::create!([
Type { fields },
in expr { fields },
...
])Expands to a tuple of create builders, one per item. Each item can be a typed creation or a scoped creation.
§Field values
§Expressions
Any Rust expression is valid as a field value — literals, variables, and function calls all work.
let name = "Alice";
toasty::create!(User { name: name, email: format!("{}@example.com", name) })§Nested struct (BelongsTo / HasOne)
Use { ... } without a type prefix to create a related record inline.
The macro calls the with_<field> closure setter on the builder.
toasty::create!(Todo {
title: "buy milk",
user: { name: "Alice" }
})
// Expands to:
// Todo::create()
// .title("buy milk")
// .with_user(|b| { let b = b.name("Alice"); b })The related record is created first and the foreign key is set automatically.
§Nested list (HasMany)
Use [{ ... }, { ... }] to create multiple related records. The macro calls
with_<field> with a CreateMany builder, invoking .with_item() for each
entry.
toasty::create!(User {
name: "Alice",
todos: [{ title: "first" }, { title: "second" }]
})
// Expands to:
// User::create()
// .name("Alice")
// .with_todos(|b| b
// .with_item(|b| { let b = b.title("first"); b })
// .with_item(|b| { let b = b.title("second"); b })
// )Items in a nested list can also be plain expressions (e.g., an existing builder value).
§Deep nesting
Nesting composes to arbitrary depth:
toasty::create!(User {
name: "Alice",
todos: [{
title: "task",
tags: [{ name: "urgent" }, { name: "work" }]
}]
})This creates a User, then a Todo linked to that user, then two Tag
records linked to that todo.
§Fields that can be omitted
| Field type | Behavior when omitted |
|---|---|
#[auto] | Value generated by the database or Toasty |
Option<T> | Defaults to None (NULL) |
#[default(expr)] | Uses the default expression |
#[update(expr)] | Uses the expression as the initial value |
HasMany<T> | No related records created |
HasOne<Option<T>> | No related record created |
BelongsTo<Option<T>> | Foreign key set to NULL |
Required fields (String, i64, non-optional BelongsTo, etc.) that are
missing do not cause a compile-time error. The insert fails at runtime with
a database constraint violation.
§Compile errors
Type prefix on nested struct:
// Error: remove the type prefix `User` — use `{ ... }` without a type name
toasty::create!(Todo { user: User { name: "Alice" } })
// Correct:
toasty::create!(Todo { user: { name: "Alice" } })Nested struct values infer their type from the field.
Nested lists:
// Error: nested lists are not supported in create!
toasty::create!(User { field: [[{ ... }]] })Missing braces or batch bracket:
// Error: expected `{` for single creation or `::[` for batch creation after type path
toasty::create!(User)§Return type
| Form | Returns |
|---|---|
Type { ... } | TypeCreate (single builder) |
in expr { ... } | Builder for the relation’s model |
Type::[ ... ] | Tuple of TypeCreate builders |
[ ... ] | Tuple of builders (one per item) |
None of the forms execute the insert on their own. Call
.exec(&mut db).await? on a single builder, or pass batch tuples to
[toasty::batch()].