toasty_driver_integration_suite/tests/
has_many_crud_multi_relations.rs

1//! Test has_many associations with multiple relations to the same model
2
3use 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    // Create a user
56    let user = User::create().name("Ann Chovey").exec(&mut db).await?;
57
58    // No TODOs
59    assert!(user.todos().exec(&mut db).await?.is_empty());
60
61    // Create a category
62    let category = Category::create().name("Food").exec(&mut db).await?;
63
64    let mut todos = vec![];
65
66    // Create some TODOs using the different builders
67    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    // Create another user and category
118    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}