toasty_driver_integration_suite/tests/
has_many_crud_multi_relations.rs1use crate::prelude::*;
4use std::collections::HashMap;
5
6#[driver_test(id(ID))]
7pub async fn crud_user_todos_categories(test: &mut Test) -> Result<()> {
8 #[derive(Debug, toasty::Model)]
9 struct User {
10 #[key]
11 #[auto]
12 id: ID,
13
14 name: String,
15
16 #[has_many]
17 todos: toasty::HasMany<Todo>,
18 }
19
20 #[derive(Debug, toasty::Model)]
21 struct Todo {
22 #[key]
23 #[auto]
24 id: ID,
25
26 #[index]
27 user_id: ID,
28
29 #[belongs_to(key = user_id, references = id)]
30 user: toasty::BelongsTo<User>,
31
32 #[index]
33 category_id: ID,
34
35 #[belongs_to(key = category_id, references = id)]
36 category: toasty::BelongsTo<Category>,
37
38 title: String,
39 }
40
41 #[derive(Debug, toasty::Model)]
42 struct Category {
43 #[key]
44 #[auto]
45 id: ID,
46
47 name: String,
48
49 #[has_many]
50 todos: toasty::HasMany<Todo>,
51 }
52
53 let mut db = test.setup_db(models!(User, Todo, Category)).await;
54
55 let user = User::create().name("Ann Chovey").exec(&mut db).await?;
57
58 assert!(user.todos().exec(&mut db).await?.is_empty());
60
61 let category = Category::create().name("Food").exec(&mut db).await?;
63
64 let mut todos = vec![];
65
66 todos.push(
68 user.todos()
69 .create()
70 .title("one")
71 .category(&category)
72 .exec(&mut db)
73 .await?,
74 );
75
76 todos.push(
77 Todo::create()
78 .title("two")
79 .user(&user)
80 .category(&category)
81 .exec(&mut db)
82 .await?,
83 );
84
85 todos.push(
86 category
87 .todos()
88 .create()
89 .title("three")
90 .user(&user)
91 .exec(&mut db)
92 .await?,
93 );
94
95 let expect: HashMap<_, _> = todos.into_iter().map(|todo| (todo.id, todo)).collect();
96
97 let lists = [
98 category.todos().exec(&mut db).await?,
99 user.todos().exec(&mut db).await?,
100 Todo::filter_by_user_id(user.id).exec(&mut db).await?,
101 ];
102
103 for list in lists {
104 assert_eq!(3, list.len());
105
106 let actual: HashMap<_, _> = list.into_iter().map(|todo| (todo.id, todo)).collect();
107 assert_eq!(3, actual.len());
108
109 for (id, actual) in actual {
110 assert_eq!(expect[&id].title, actual.title);
111
112 let user = actual.user().get(&mut db).await?;
113 assert_eq!(user.name, "Ann Chovey");
114 }
115 }
116
117 let user2 = User::create().name("Not ann").exec(&mut db).await?;
119 let category2 = Category::create().name("drink").exec(&mut db).await?;
120
121 category
122 .todos()
123 .create()
124 .user(&user2)
125 .title("NOPE")
126 .exec(&mut db)
127 .await?;
128 user.todos()
129 .create()
130 .category(&category2)
131 .title("FAIL")
132 .exec(&mut db)
133 .await?;
134
135 async fn check_todo_list(
136 db: &mut toasty::Db,
137 expect: &HashMap<ID, Todo>,
138 list: Vec<Todo>,
139 ) -> Result<()> {
140 assert_eq!(3, list.len(), "list={list:#?}");
141
142 let actual: HashMap<_, _> = list.into_iter().map(|todo| (todo.id, todo)).collect();
143
144 assert_eq!(3, actual.len(), "actual={actual:#?}");
145
146 for (id, actual) in actual {
147 assert_eq!(expect[&id].title, actual.title);
148 let category = actual.category().get(db).await?;
149 assert_eq!(category.name, "Food");
150 }
151 Ok(())
152 }
153
154 let list = category
155 .todos()
156 .query(Todo::fields().user().eq(&user))
157 .exec(&mut db)
158 .await?;
159 check_todo_list(&mut db, &expect, list).await?;
160
161 let list = user
162 .todos()
163 .query(Todo::fields().category().eq(&category))
164 .exec(&mut db)
165 .await?;
166 check_todo_list(&mut db, &expect, list).await?;
167
168 let list = Todo::filter_by_user_id(user.id)
169 .filter(Todo::fields().category().eq(&category))
170 .exec(&mut db)
171 .await?;
172 check_todo_list(&mut db, &expect, list).await
173}