Inspect local data with Studio
You have created users and posts. Now look at the rows without writing another query. Point Studio at your local project database:
If you need one first, scaffold it with rent new, add models with
rent init User Post Comment, and apply them with
rent migrate dev --name initial. An in-memory SQLite database does not survive
its process, so use the project's rent.db for browsing:
rent studioChoose users, posts, or comments in the sidebar. Studio shows the catalog-derived columns and primary key,
then loads the first page of rows. It starts read-only so exploration cannot accidentally change the tutorial data.
To edit local development data, stop Studio and opt into editing:
rent studio --allow-writesDouble-click a cell and enter its new value as JSON. For example, a string must include JSON quotes:
"A clearer post title"Studio sends a parameterized update constrained by the row's full primary key and accepts success only when exactly one row changes.
For permission-aware browsing, continue with Studio viewer mode.
Complete example
Download this project, or copy the files below into an empty directory.
Replace RENT_REPOSITORY_URL in Cargo.toml with the URL supplied with your preview access. Use the matching Rent CLI release.
Create a persistent database, add a post, then open Studio:
export DATABASE_URL='sqlite://lesson.db?mode=rwc'
rent generate
rent migrate dev --name initial
cargo run
rent studioCargo.toml
[package]
name = "rent-lesson-21-studio"
version = "0.1.0"
edition = "2024"
[workspace]
[[bin]]
name = "rent-lesson-21-studio"
path = "main.rs"
[dependencies]
rent = { git = "RENT_REPOSITORY_URL", tag = "v0.8.6", default-features = false, features = ["sqlite", "migrate", "extensions"] }
anyhow = "1.0.104"
tokio = { version = "1.53.1", features = ["full"] }
tempfile = "3.27.0"
# Used by the generated client after `rent generate`.
[package.metadata.cargo-machete]
ignored = ["rent"]rent.toml
schema = "schema.rsl"
generated = "generated"
migrations = "migrations"
[database]
dialect = "sqlite"
backends = ["sqlite"]schema.rsl
datasource db {
provider = "sqlite"
}
model User {
id BigInt @id
name String
posts Post[]
comments Comment[] @relation("CommentAuthor")
profile Profile?
@@map("users")
}
model Post {
id BigInt @id
title String
body String
published Boolean
author_id BigInt
author User @relation(fields: [author_id], references: [id])
comments Comment[]
@@map("posts")
}
model Comment {
id BigInt @id
body String
post_id BigInt
author_id BigInt
post Post @relation(fields: [post_id], references: [id], onDelete: Cascade)
author User @relation("CommentAuthor", fields: [author_id], references: [id])
@@map("comments")
}
model Profile {
id BigInt @id
bio String
user_id BigInt @unique
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
@@map("profiles")
}main.rs
use anyhow::Result;
#[allow(dead_code, unused_imports)]
#[rustfmt::skip]
#[path = "generated/mod.rs"]
mod generated;
async fn example(url: &str) -> Result<()> {
let client = generated::client::Client::connect(url).await?;
let maya = client
.upsert_user(generated::user::unique::id)
.id(1)
.name("Maya")
.save()
.await?;
client
.upsert_post(generated::post::unique::id)
.id(1)
.title("Welcome")
.body("Open this post in Studio")
.published(false)
.author_id(maya.id)
.save()
.await?;
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
example(&std::env::var("DATABASE_URL")?).await
}
#[cfg(test)]
mod test_support;
#[cfg(test)]
mod tests {
#[tokio::test]
async fn example_runs() -> anyhow::Result<()> {
let (_directory, url) = super::test_support::database()?;
super::example(&url).await
}
}test_support.rs
use anyhow::{Context, Result, ensure};
use std::process::Command;
pub fn database() -> Result<(tempfile::TempDir, String)> {
let directory = tempfile::tempdir()?;
std::fs::write(directory.path().join("schema.rsl"), include_str!("schema.rsl"))?;
std::fs::write(directory.path().join("rent.toml"), r#"schema = "schema.rsl""#)?;
let url = format!("sqlite://{}?mode=rwc", directory.path().join("app.db").display());
let executable = std::env::var("RENT_CLI").unwrap_or_else(|_| "rent".into());
let output = Command::new(executable)
.arg("migrate")
.arg("dev")
.arg("--root")
.arg(directory.path())
.arg("--to")
.arg("schema.rsl")
.arg("--database-url")
.arg(&url)
.output()
.context("run the Rent CLI")?;
ensure!(
output.status.success(),
"migration failed: {}",
String::from_utf8_lossy(&output.stderr)
);
Ok((directory, url))
}