Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting Started

This chapter walks through creating a project, defining a model, and running your first queries.

Create a new project

cargo new my-app
cd my-app

Add the following dependencies to Cargo.toml:

[dependencies]
toasty = { version = "0.3", features = ["sqlite"] }
tokio = { version = "1", features = ["full"] }

The sqlite feature enables the SQLite driver. Toasty also supports postgresql, mysql, and dynamodb — swap the feature flag to use a different database.

Define a model

Replace the contents of src/main.rs with:

use toasty::Model;
#[derive(Debug, toasty::Model)]
struct User {
    #[key]
    #[auto]
    id: u64,

    name: String,

    #[unique]
    email: String,
}

async fn __example() -> toasty::Result<()> {
#[tokio::main]
async fn main() -> toasty::Result<()> {
    // Build a Db handle, registering all models in this crate
    let mut db = toasty::Db::builder()
        .models(toasty::models!(crate::*))
        .connect("sqlite::memory:")
        .await?;

    // Create tables based on registered models
    db.push_schema().await?;

    // Create a user
    let user = toasty::create!(User {
        name: "Alice",
        email: "alice@example.com",
    })
    .exec(&mut db)
    .await?;

    println!("Created: {:?}", user.name);

    // Fetch the user back by primary key
    let found = User::get_by_id(&mut db, &user.id).await?;
    println!("Found: {:?}", found.email);

    Ok(())
}
Ok(())
}

Run it:

cargo run

You should see:

Created: "Alice"
Found: "alice@example.com"

What just happened

The #[derive(toasty::Model)] macro read the User struct and generated several types and methods at compile time:

You wroteToasty generated
struct Usertoasty::create!(User { ... }) — insert rows
#[key] on idUser::get_by_id() — fetch by primary key
#[auto] on idAuto-generates an ID when you create a user
#[unique] on emailUser::get_by_email() — fetch by email

You did not write any of these methods. They come from the derive macro. The rest of this guide shows everything the macro can generate and how to use it.

Connecting to a database

Db::builder() creates a builder where you provide your models and then connect to a database. Toasty uses the registered models to infer the full database schema — tables, columns, indexes, and relationships between models.

let mut db = toasty::Db::builder()
    .models(toasty::models!(crate::*))
    .connect("sqlite::memory:")
    .await?;

crate::* automatically discovers all #[derive(Model)] and #[derive(Embed)] types in your crate. You can also list models individually (toasty::models!(User, Post)), register all models from an external crate (toasty::models!(other_crate::*)), or combine these forms freely.

The connection URL determines which database driver to use. See Database Setup for more on model registration, connection URLs, and supported databases.

Creating tables

db.push_schema() creates all tables and indexes defined by your models. See Migrations and Schema Management for more on managing your database schema.