Skip to main content

Quick Start

Let's go from zero to a working query in 5 minutes.

1. Define a Modelโ€‹

use ryx_rs::model;
use ryx_rs::ObjectsManager;

#[model]
#[table("posts")]
struct Post {
#[field(pk)]
id: i64,
title: String,
slug: String,
views: i64,
active: bool,
}
  • #[model] derives Model, FromRow, and more.
  • #[field(pk)] marks the primary key.
  • #[table("posts") optionally overrides the table name.

2. Configure & Migrateโ€‹

use ryx_rs::migration::MigrationRunner;

async fn run() -> ryx_rs::RyxResult<()> {
ryx_rs::init().await?;
MigrationRunner::new()
.live(true) // apply directly โ€” no files needed
.model::<Post>()
.run().await?;
Ok(())
}

init() reads a ryx.toml or uses the DATABASE_URL env var.

tip

For production, use file-based YAML migrations with the CLI:

ryx makemigrations --dir migrations/
ryx migrate --dir migrations/
ryx showmigrations

See Migrations for the full guide.

3. Create Recordsโ€‹

let post = ObjectsManager::<Post>::new().create()
.set("title", "Hello Ryx")
.set("slug", "hello-ryx")
.set("views", 42i64)
.set("active", true)
.save().await?;

4. Queryโ€‹

// All active posts, newest first
let posts: Vec<Post> = ObjectsManager::<Post>::new()
.filter("active", true)
.order_by("-views")
.all().await?;

// First match
let first: Option<Post> = ObjectsManager::<Post>::new()
.filter("active", true)
.order_by("title")
.first().await?;

// Count
let count = ObjectsManager::<Post>::new()
.filter("active", true)
.count().await?;

// Check existence
let exists = ObjectsManager::<Post>::new()
.filter("title__startswith", "Draft")
.exists().await?;

5. Update & Deleteโ€‹

// Bulk update
ObjectsManager::<Post>::new()
.filter("active", false)
.update(vec![("active", true)])
.await?;

// Bulk delete
ObjectsManager::<Post>::new()
.filter("views", 0i64)
.delete().await?;

Complete Exampleโ€‹

use ryx_rs::model;
use ryx_rs::migration::MigrationRunner;
use ryx_rs::ObjectsManager;

#[model]
#[table("posts")]
struct Post {
#[field(pk)]
id: i64,
title: String,
slug: String,
views: i64,
active: bool,
}

#[tokio::main]
async fn main() -> ryx_rs::RyxResult<()> {
ryx_rs::init().await?;
MigrationRunner::new().live(true).model::<Post>().run().await?;

ObjectsManager::<Post>::new().create()
.set("title", "Hello Ryx")
.set("slug", "hello-ryx")
.set("views", 100i64)
.save().await?;

let posts: Vec<Post> = ObjectsManager::<Post>::new()
.filter("active", true)
.order_by("-views")
.all().await?;

println!("Found {} posts", posts.len());

let stats = ObjectsManager::<Post>::new()
.all()
.aggregate(&[
ryx_rs::agg::count("total", "id"),
ryx_rs::agg::avg("avg", "views"),
]).await?;

println!("Stats: {:?}", stats);

Ok(())
}

Next Stepsโ€‹

  • Models โ€” Deep dive into model definitions
  • QuerySet โ€” The full query API