One-to-one and many-to-one relationships
Let's say you want a user to be able to have projects. You can use the
#[many_to_one]
attribute in order to do so. Let's take the following code as
an example:
#![allow(unused)] fn main() { extern crate ergol; use ergol::prelude::*; #[ergol] pub struct User { #[id] pub id: i32, #[unique] pub username: String, pub password: String, pub age: Option<i32>, } #[ergol] pub struct Project { #[id] pub id: i32, pub name: String, #[many_to_one(projects)] pub owner: User, } }
Once you have defined this struct, many more functions become available:
extern crate tokio; extern crate ergol; use ergol::prelude::*; #[ergol] pub struct User { #[id] pub id: i32, #[unique] pub username: String, pub password: String, pub age: Option<i32>, } #[ergol] pub struct Project { #[id] pub id: i32, pub name: String, #[many_to_one(projects)] pub owner: User, } #[tokio::main] async fn main() -> Result<(), ergol::tokio_postgres::Error> { let (db, connection) = ergol::connect( "host=localhost user=ergol password=ergol dbname=ergol", ergol::tokio_postgres::NoTls, ) .await?; tokio::spawn(async move { if let Err(e) = connection.await { eprintln!("connection error: {}", e); } }); // Drop the tables if they exist Project::drop_table().execute(&db).await.ok(); User::drop_table().execute(&db).await.ok(); // Create the tables User::create_table().execute(&db).await?; Project::create_table().execute(&db).await?; // Create two users and save them into the database let thomas: User = User::create("thomas", "pa$$w0rd", 28).save(&db).await?; User::create("nicolas", "pa$$w0rd", 28).save(&db).await?; // Create some projects for the user let project: Project = Project::create("My first project", &thomas).save(&db).await?; Project::create("My second project", &thomas).save(&db).await?; // You can easily find all projects from the user let projects: Vec<Project> = thomas.projects(&db).await?; // You can also find the owner of a project let owner: User = projects[0].owner(&db).await?; Ok(()) }
You can similarly have one-to-one relationship between a user and a project by
using the #[one_to_one]
attribute:
#![allow(unused)] fn main() { extern crate ergol; use ergol::prelude::*; #[ergol] pub struct User { #[id] pub id: i32, #[unique] pub username: String, pub password: String, pub age: Option<i32>, } #[ergol] pub struct Project { #[id] pub id: i32, pub name: String, #[one_to_one(project)] pub owner: User, } }
This will add the UNIQUE
attribute in the database and make the project
method only return an option:
extern crate tokio; extern crate ergol; use ergol::prelude::*; #[ergol] pub struct User { #[id] pub id: i32, #[unique] pub username: String, pub password: String, pub age: Option<i32>, } #[ergol] pub struct Project { #[id] pub id: i32, pub name: String, #[one_to_one(project)] pub owner: User, } #[tokio::main] async fn main() -> Result<(), ergol::tokio_postgres::Error> { let (db, connection) = ergol::connect( "host=localhost user=ergol password=ergol dbname=ergol2", ergol::tokio_postgres::NoTls, ) .await?; tokio::spawn(async move { if let Err(e) = connection.await { eprintln!("connection error: {}", e); } }); Project::drop_table().execute(&db).await.ok(); User::drop_table().execute(&db).await.ok(); User::create_table().execute(&db).await?; Project::create_table().execute(&db).await?; let thomas: User = User::create("thomas", "pa$$w0rd", 28).save(&db).await?; // You can easily find a user's project let project: Option<Project> = thomas.project(&db).await?; Ok(()) }
Note that that way, a project has exactly one owner, but a user can have no project.