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 wrote | Toasty generated |
|---|---|
struct User | toasty::create!(User { ... }) — insert rows |
#[key] on id | User::get_by_id() — fetch by primary key |
#[auto] on id | Auto-generates an ID when you create a user |
#[unique] on email | User::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.