toasty_driver_integration_suite/tests/
relation_has_many_boxed_fk.rs

1use crate::prelude::*;
2
3use std::{rc::Rc, sync::Arc};
4
5#[driver_test(requires(sql))]
6pub async fn boxed_u64_fk_crud(test: &mut Test) -> Result<()> {
7    #[derive(Debug, toasty::Model)]
8    struct User {
9        #[key]
10        #[auto]
11        id: u64,
12        name: String,
13        #[has_many]
14        todos: toasty::HasMany<Todo>,
15    }
16
17    #[derive(Debug, toasty::Model)]
18    struct Todo {
19        #[key]
20        #[auto]
21        id: u64,
22        #[index]
23        user_id: Box<u64>,
24        #[belongs_to(key = user_id, references = id)]
25        user: toasty::BelongsTo<User>,
26        title: String,
27    }
28
29    let mut db = test.setup_db(models!(User, Todo)).await;
30
31    // Create a user
32    let user = toasty::create!(User { name: "Alice" })
33        .exec(&mut db)
34        .await?;
35
36    // No todos yet
37    let todos: Vec<_> = user.todos().exec(&mut db).await?;
38    assert!(todos.is_empty());
39
40    // Create a todo via the has_many association
41    let todo = user
42        .todos()
43        .create()
44        .title("Buy groceries")
45        .exec(&mut db)
46        .await?;
47
48    assert_eq!(todo.title, "Buy groceries");
49    assert_eq!(*todo.user_id, user.id);
50
51    // Query back by FK
52    let todos: Vec<_> = Todo::filter_by_user_id(user.id).exec(&mut db).await?;
53    assert_eq!(todos.len(), 1);
54    assert_eq!(todos[0].title, "Buy groceries");
55
56    // Create another todo directly
57    let todo2 = Todo::create()
58        .user(&user)
59        .title("Walk the dog")
60        .exec(&mut db)
61        .await?;
62
63    assert_eq!(*todo2.user_id, user.id);
64
65    // List all user's todos
66    let todos: Vec<_> = user.todos().exec(&mut db).await?;
67    assert_eq!(todos.len(), 2);
68
69    // Look up user from todo FK
70    let found_user = User::get_by_id(&mut db, &*todo.user_id).await?;
71    assert_eq!(found_user.id, user.id);
72
73    Ok(())
74}
75
76#[driver_test(requires(sql))]
77pub async fn boxed_u64_fk_batch_create(test: &mut Test) -> Result<()> {
78    #[derive(Debug, toasty::Model)]
79    struct User {
80        #[key]
81        #[auto]
82        id: u64,
83        name: String,
84        #[has_many]
85        todos: toasty::HasMany<Todo>,
86    }
87
88    #[derive(Debug, toasty::Model)]
89    struct Todo {
90        #[key]
91        #[auto]
92        id: u64,
93        #[index]
94        user_id: Box<u64>,
95        #[belongs_to(key = user_id, references = id)]
96        user: toasty::BelongsTo<User>,
97        title: String,
98    }
99
100    let mut db = test.setup_db(models!(User, Todo)).await;
101
102    // Create user with todos in one batch
103    let user = User::create()
104        .name("Bob")
105        .todo(Todo::create().title("First task"))
106        .todo(Todo::create().title("Second task"))
107        .exec(&mut db)
108        .await?;
109
110    let todos: Vec<_> = user.todos().exec(&mut db).await?;
111    assert_eq!(todos.len(), 2);
112
113    for todo in &todos {
114        assert_eq!(*todo.user_id, user.id);
115    }
116
117    Ok(())
118}
119
120#[driver_test(requires(sql))]
121pub async fn boxed_u64_fk_delete_and_update(test: &mut Test) -> Result<()> {
122    #[derive(Debug, toasty::Model)]
123    struct User {
124        #[key]
125        #[auto]
126        id: u64,
127        name: String,
128        #[has_many]
129        todos: toasty::HasMany<Todo>,
130    }
131
132    #[derive(Debug, toasty::Model)]
133    struct Todo {
134        #[key]
135        #[auto]
136        id: u64,
137        #[index]
138        user_id: Box<u64>,
139        #[belongs_to(key = user_id, references = id)]
140        user: toasty::BelongsTo<User>,
141        title: String,
142    }
143
144    let mut db = test.setup_db(models!(User, Todo)).await;
145
146    let user = toasty::create!(User { name: "Carol" })
147        .exec(&mut db)
148        .await?;
149
150    let mut todo = user
151        .todos()
152        .create()
153        .title("Original")
154        .exec(&mut db)
155        .await?;
156
157    // Update the todo title
158    todo.update().title("Updated").exec(&mut db).await?;
159
160    let reloaded = Todo::get_by_id(&mut db, &todo.id).await?;
161    assert_eq!(reloaded.title, "Updated");
162    assert_eq!(*reloaded.user_id, user.id);
163
164    // Delete the todo
165    reloaded.delete().exec(&mut db).await?;
166
167    let todos: Vec<_> = user.todos().exec(&mut db).await?;
168    assert!(todos.is_empty());
169
170    Ok(())
171}
172
173#[driver_test(requires(sql))]
174pub async fn arc_u64_fk_crud(test: &mut Test) -> Result<()> {
175    #[derive(Debug, toasty::Model)]
176    struct User {
177        #[key]
178        #[auto]
179        id: u64,
180        name: String,
181        #[has_many]
182        todos: toasty::HasMany<Todo>,
183    }
184
185    #[derive(Debug, toasty::Model)]
186    struct Todo {
187        #[key]
188        #[auto]
189        id: u64,
190        #[index]
191        user_id: Arc<u64>,
192        #[belongs_to(key = user_id, references = id)]
193        user: toasty::BelongsTo<User>,
194        title: String,
195    }
196
197    let mut db = test.setup_db(models!(User, Todo)).await;
198
199    let user = toasty::create!(User { name: "Alice" })
200        .exec(&mut db)
201        .await?;
202
203    // Create via association
204    let todo = user
205        .todos()
206        .create()
207        .title("Arc task")
208        .exec(&mut db)
209        .await?;
210
211    assert_eq!(*todo.user_id, user.id);
212
213    // Query back by FK
214    let todos: Vec<_> = Todo::filter_by_user_id(user.id).exec(&mut db).await?;
215    assert_eq!(todos.len(), 1);
216    assert_eq!(todos[0].title, "Arc task");
217
218    // Create directly
219    let todo2 = Todo::create()
220        .user(&user)
221        .title("Arc task 2")
222        .exec(&mut db)
223        .await?;
224
225    assert_eq!(*todo2.user_id, user.id);
226
227    // Batch create
228    let user2 = User::create()
229        .name("Bob")
230        .todo(Todo::create().title("Batch 1"))
231        .todo(Todo::create().title("Batch 2"))
232        .exec(&mut db)
233        .await?;
234
235    let todos: Vec<_> = user2.todos().exec(&mut db).await?;
236    assert_eq!(todos.len(), 2);
237
238    for todo in &todos {
239        assert_eq!(*todo.user_id, user2.id);
240    }
241
242    Ok(())
243}
244
245#[driver_test(requires(sql))]
246pub async fn rc_u64_fk_crud(test: &mut Test) -> Result<()> {
247    #[derive(Debug, toasty::Model)]
248    struct User {
249        #[key]
250        #[auto]
251        id: u64,
252        name: String,
253        #[has_many]
254        todos: toasty::HasMany<Todo>,
255    }
256
257    #[derive(Debug, toasty::Model)]
258    struct Todo {
259        #[key]
260        #[auto]
261        id: u64,
262        #[index]
263        user_id: Rc<u64>,
264        #[belongs_to(key = user_id, references = id)]
265        user: toasty::BelongsTo<User>,
266        title: String,
267    }
268
269    let mut db = test.setup_db(models!(User, Todo)).await;
270
271    let user = toasty::create!(User { name: "Alice" })
272        .exec(&mut db)
273        .await?;
274
275    // Create via association
276    let todo = user.todos().create().title("Rc task").exec(&mut db).await?;
277
278    assert_eq!(*todo.user_id, user.id);
279
280    // Query back by FK
281    let todos: Vec<_> = Todo::filter_by_user_id(user.id).exec(&mut db).await?;
282    assert_eq!(todos.len(), 1);
283    assert_eq!(todos[0].title, "Rc task");
284
285    // Create directly
286    let todo2 = Todo::create()
287        .user(&user)
288        .title("Rc task 2")
289        .exec(&mut db)
290        .await?;
291
292    assert_eq!(*todo2.user_id, user.id);
293
294    // Batch create
295    let user2 = User::create()
296        .name("Bob")
297        .todo(Todo::create().title("Batch 1"))
298        .todo(Todo::create().title("Batch 2"))
299        .exec(&mut db)
300        .await?;
301
302    let todos: Vec<_> = user2.todos().exec(&mut db).await?;
303    assert_eq!(todos.len(), 2);
304
305    for todo in &todos {
306        assert_eq!(*todo.user_id, user2.id);
307    }
308
309    Ok(())
310}