create

Macro create 

Source
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 typeBehavior 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

FormReturns
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()].