toasty_driver_integration_suite/tests/
belongs_to_self_referential.rs1use crate::prelude::*;
2use std::collections::HashMap;
3
4#[driver_test(id(ID))]
5pub async fn crud_person_self_referential(t: &mut Test) -> Result<()> {
6 #[derive(Debug, toasty::Model)]
7 struct Person {
8 #[key]
9 #[auto]
10 id: ID,
11
12 name: String,
13
14 #[index]
15 parent_id: Option<ID>,
16
17 #[belongs_to(key = parent_id, references = id)]
18 parent: toasty::BelongsTo<Option<Person>>,
19
20 #[has_many(pair = parent)]
21 children: toasty::HasMany<Person>,
22 }
23
24 let mut db = t.setup_db(models!(Person)).await;
25
26 let p1 = Person::create().name("person 1").exec(&mut db).await?;
27
28 assert_none!(p1.parent_id);
29
30 let p2 = Person::create()
32 .name("person 2")
33 .parent(&p1)
34 .exec(&mut db)
35 .await?;
36
37 assert_eq!(p2.parent_id, Some(p1.id));
38
39 let p3 = Person::create()
41 .name("person 3")
42 .parent_id(p1.id)
43 .exec(&mut db)
44 .await?;
45
46 assert_eq!(p3.parent_id, Some(p1.id));
47
48 let assert = |children: &[Person]| {
49 assert_eq!(children.len(), 2);
50
51 let children: HashMap<_, _> = children.iter().map(|p| (p.id, p)).collect();
52 assert_eq!(children.len(), 2);
53
54 for (id, child) in &children {
55 if id == &p2.id {
56 assert_eq!(child.name, "person 2");
57 } else if id == &p3.id {
58 assert_eq!(child.name, "person 3");
59 } else {
60 panic!("Unexpected child ID: {}", id);
61 }
62 }
63 };
64
65 let children: Vec<_> = p1.children().exec(&mut db).await?;
67 assert(&children);
68
69 let p1 = Person::filter_by_id(p1.id)
71 .include(Person::fields().children())
72 .get(&mut db)
73 .await?;
74
75 assert(p1.children.get());
76 Ok(())
77}