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

§Field syntax

Fields inside { ... } can use either explicit or shorthand syntax:

  • Explicit: field: expr — sets the field to the given expression.
  • Shorthand: field — equivalent to field: field, using a variable with the same name as the field.

These can be mixed freely, just like Rust struct literals:

let name = "Alice".to_string();
toasty::create!(User { name, email: "alice@example.com" })

§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 toasty::batch([builder1, builder2, ...]) and returns Vec<Type> when executed:

let users = toasty::create!(User::[
    { name: "Alice" },
    { name: "Bob" },
])
.exec(&mut db)
.await?;
// users: Vec<User>

§Tuple

toasty::create!((
    Type1 { fields },
    Type2 { fields },
    ...
))

Expands to toasty::batch((builder1, builder2, ...)) and returns a tuple matching the input types:

let (user, post) = toasty::create!((
    User { name: "Alice" },
    Post { title: "Hello" },
))
.exec(&mut db)
.await?;
// (User, Post)

§Mixed tuple

Typed batches and single creates can be mixed inside a tuple:

let (users, post) = toasty::create!((
    User::[ { name: "Alice" }, { name: "Bob" } ],
    Post { title: "Hello" },
))
.exec(&mut db)
.await?;
// (Vec<User>, Post)

§Field values

§Expressions

Any Rust expression is valid as a field value — literals, variables, and function calls all work. When a variable has the same name as the field, you can use the shorthand syntax (just name instead of name: name):

let name = "Alice";
let _ = toasty::create!(User { name, email: format!("{}@example.com", name) });

When the variable name differs from the field name, use the explicit field: expr form:

let user_name = "Alice";
let _ = toasty::create!(User { name: user_name });

§Nested struct (BelongsTo / HasOne)

Use { ... } without a type prefix to create a related record inline. The macro expands the nested fields into a create builder and passes it to the field’s setter method.

let _ = toasty::create!(Todo {
    title: "buy milk",
    user: { name: "Alice" }
});
// Expands to:
// Todo::create()
//     .title("buy milk")
//     .user(Todo::fields().user().create().name("Alice"))

The related record is created first and the foreign key is set automatically.

§Nested list (HasMany)

Use [{ ... }, { ... }] to create multiple related records. The macro expands each entry into a create builder and passes them as an array to the plural field setter.

let _ = toasty::create!(User {
    name: "Alice",
    todos: [{ title: "first" }, { title: "second" }]
});
// Expands to:
// User::create()
//     .name("Alice")
//     .todos([
//         User::fields().todos().create().title("first"),
//         User::fields().todos().create().title("second"),
//     ])

Items in a nested list can also be plain expressions (e.g., an existing builder value).

§Deep nesting

Nesting composes to arbitrary depth:

let _ = 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:

let _ = 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::[ ... ]Batch — executes to Vec<Type>
( ... )Batch — executes to tuple of results

Single and scoped forms return a builder — call .exec(&mut db).await?. Batch and tuple forms return a Batch — also call .exec(&mut db).await?.