toasty_driver_integration_suite/tests/
relation_has_one_crud.rs1use crate::prelude::*;
2
3#[driver_test(id(ID), scenario(crate::scenarios::has_one_optional_belongs_to))]
4pub async fn crud_has_one_bi_direction_optional(test: &mut Test) -> Result<()> {
5 let mut db = setup(test).await;
6
7 let user = User::create().name("Jane Doe").exec(&mut db).await?;
9
10 assert_none!(user.profile().exec(&mut db).await?);
12
13 let profile = user
15 .profile()
16 .create()
17 .bio("a person")
18 .exec(&mut db)
19 .await?;
20
21 let profile_reload = user.profile().exec(&mut db).await?.unwrap();
23 assert_eq!(profile.id, profile_reload.id);
24
25 let user_reload = profile.user().exec(&mut db).await?.unwrap();
27 assert_eq!(user.id, user_reload.id);
28
29 let mut user = User::create()
31 .name("Tim Apple")
32 .profile(Profile::create().bio("an apple a day"))
33 .exec(&mut db)
34 .await?;
35
36 let profile = user.profile().exec(&mut db).await?.unwrap();
37 assert_eq!(profile.bio, "an apple a day");
38
39 assert_eq!(user.id, profile.user().exec(&mut db).await?.unwrap().id);
41
42 user.update()
44 .profile(Profile::create().bio("keeps the doctor away"))
45 .exec(&mut db)
46 .await?;
47
48 let profile = user.profile().exec(&mut db).await?.unwrap();
50 assert_eq!(profile.bio, "keeps the doctor away");
51 assert_eq!(user.id, profile.user().exec(&mut db).await?.unwrap().id);
52
53 user.update().profile(None).exec(&mut db).await?;
55
56 assert!(user.profile().exec(&mut db).await?.is_none());
58
59 let profile_reloaded = Profile::filter_by_id(profile.id).get(&mut db).await?;
60 assert_none!(profile_reloaded.user_id);
61
62 user.update()
63 .profile(&profile_reloaded)
64 .exec(&mut db)
65 .await?;
66
67 let profile_reloaded = Profile::get_by_id(&mut db, &profile.id).await?;
68 assert_eq!(&user.id, profile_reloaded.user_id.as_ref().unwrap());
69
70 profile_reloaded.delete().exec(&mut db).await?;
72
73 let mut user_reloaded = User::get_by_id(&mut db, &user.id).await?;
74 assert_none!(user_reloaded.profile().exec(&mut db).await?);
75
76 user_reloaded
78 .update()
79 .profile(Profile::create().bio("hello"))
80 .exec(&mut db)
81 .await?;
82
83 let profile_id = user_reloaded.profile().exec(&mut db).await?.unwrap().id;
84
85 user_reloaded.delete().exec(&mut db).await?;
87
88 let profile_reloaded = Profile::get_by_id(&mut db, &profile_id).await?;
89 assert_none!(profile_reloaded.user_id);
90 Ok(())
91}
92
93#[driver_test(id(ID))]
94#[should_panic]
95pub async fn crud_has_one_required_belongs_to_optional(test: &mut Test) -> Result<()> {
96 #[derive(Debug, toasty::Model)]
97 struct User {
98 #[key]
99 #[auto]
100 id: ID,
101
102 #[has_one]
103 profile: toasty::HasOne<Profile>,
104 }
105
106 #[derive(Debug, toasty::Model)]
107 struct Profile {
108 #[key]
109 #[auto]
110 id: ID,
111
112 #[unique]
113 user_id: Option<ID>,
114
115 #[belongs_to(key = user_id, references = id)]
116 user: toasty::BelongsTo<Option<User>>,
117
118 bio: String,
119 }
120
121 let mut db = test.setup_db(models!(User, Profile)).await;
122
123 let user = User::create()
125 .profile(Profile::create().bio("an apple a day"))
126 .exec(&mut db)
127 .await?;
128
129 let profile = user.profile().exec(&mut db).await?;
130 assert_eq!(profile.bio, "an apple a day");
131
132 assert_eq!(user.id, profile.user().exec(&mut db).await?.unwrap().id);
134
135 user.delete().exec(&mut db).await?;
137 let profile_reloaded = Profile::get_by_id(&mut db, &profile.id).await?;
138 assert_none!(profile_reloaded.user_id);
139
140 assert_err!(User::create().exec(&mut db).await);
142 Ok(())
143}
144
145#[driver_test(id(ID))]
146pub async fn update_belongs_to_with_required_has_one_pair(test: &mut Test) -> Result<()> {
147 #[derive(Debug, toasty::Model)]
148 struct User {
149 #[key]
150 #[auto]
151 id: ID,
152
153 #[has_one]
154 profile: toasty::HasOne<Profile>,
155 }
156
157 #[derive(Debug, toasty::Model)]
158 struct Profile {
159 #[key]
160 #[auto]
161 id: ID,
162
163 #[unique]
164 user_id: Option<ID>,
165
166 #[belongs_to(key = user_id, references = id)]
167 user: toasty::BelongsTo<Option<User>>,
168
169 bio: String,
170 }
171
172 let mut db = test.setup_db(models!(User, Profile)).await;
173
174 let u1 = User::create()
176 .profile(Profile::create().bio("an apple a day"))
177 .exec(&mut db)
178 .await?;
179
180 let mut p1 = u1.profile().exec(&mut db).await?;
181 assert_eq!(p1.bio, "an apple a day");
182
183 let u2 = User::create()
185 .profile(Profile::create().bio("I plant trees"))
186 .exec(&mut db)
187 .await?;
188
189 let p2 = u2.profile().exec(&mut db).await?;
190 assert_eq!(p2.bio, "I plant trees");
191
192 p1.update().user(&u2).exec(&mut db).await?;
194
195 assert_err!(User::get_by_id(&mut db, &u1.id).await);
198 let p2_reloaded = Profile::get_by_id(&mut db, &p2.id).await?;
200 assert_none!(p2_reloaded.user_id);
201
202 Ok(())
249}
250
251#[driver_test(id(ID))]
252pub async fn crud_has_one_optional_belongs_to_required(test: &mut Test) -> Result<()> {
253 #[derive(Debug, toasty::Model)]
254 struct User {
255 #[key]
256 #[auto]
257 id: ID,
258
259 #[has_one]
260 profile: toasty::HasOne<Option<Profile>>,
261 }
262
263 #[derive(Debug, toasty::Model)]
264 struct Profile {
265 #[key]
266 #[auto]
267 id: ID,
268
269 #[unique]
270 user_id: ID,
271
272 #[belongs_to(key = user_id, references = id)]
273 user: toasty::BelongsTo<User>,
274
275 bio: String,
276 }
277
278 let mut db = test.setup_db(models!(User, Profile)).await;
279
280 let user = User::create()
282 .profile(Profile::create().bio("an apple a day"))
283 .exec(&mut db)
284 .await?;
285
286 let profile = user.profile().exec(&mut db).await?.unwrap();
287 assert_eq!(profile.bio, "an apple a day");
288
289 assert_eq!(user.id, profile.user().exec(&mut db).await?.id);
291
292 user.delete().exec(&mut db).await?;
294 assert_err!(Profile::get_by_id(&mut db, &profile.id).await);
295 Ok(())
296}
297
298#[driver_test(id(ID))]
299pub async fn set_has_one_by_value_in_update_query(test: &mut Test) -> Result<()> {
300 #[derive(Debug, toasty::Model)]
301 struct User {
302 #[key]
303 #[auto]
304 id: ID,
305
306 #[has_one]
307 profile: toasty::HasOne<Option<Profile>>,
308 }
309
310 #[derive(Debug, toasty::Model)]
311 struct Profile {
312 #[key]
313 #[auto]
314 id: ID,
315
316 #[unique]
317 user_id: Option<ID>,
318
319 #[belongs_to(key = user_id, references = id)]
320 user: toasty::BelongsTo<Option<User>>,
321 }
322
323 let mut db = test.setup_db(models!(User, Profile)).await;
324
325 let user = User::create().exec(&mut db).await?;
326 let profile = Profile::create().exec(&mut db).await?;
327
328 User::filter_by_id(user.id)
329 .update()
330 .profile(&profile)
331 .exec(&mut db)
332 .await?;
333
334 let profile_reload = user.profile().exec(&mut db).await?.unwrap();
335 assert_eq!(profile_reload.id, profile.id);
336
337 assert_eq!(profile_reload.user_id.as_ref().unwrap(), &user.id);
338 Ok(())
339}
340
341#[driver_test(id(ID))]
342pub async fn unset_has_one_in_batch_update(test: &mut Test) -> Result<()> {
343 #[derive(Debug, toasty::Model)]
344 struct User {
345 #[key]
346 #[auto]
347 id: ID,
348
349 #[index]
350 name: String,
351
352 #[has_one]
353 profile: toasty::HasOne<Option<Profile>>,
354 }
355
356 #[derive(Debug, toasty::Model)]
357 struct Profile {
358 #[key]
359 #[auto]
360 id: ID,
361
362 #[unique]
363 user_id: ID,
364
365 #[belongs_to(key = user_id, references = id)]
366 user: toasty::BelongsTo<User>,
367 }
368
369 let mut db = test.setup_db(models!(User, Profile)).await;
370
371 let u1 = User::create()
373 .name("alice")
374 .profile(Profile::create())
375 .exec(&mut db)
376 .await?;
377 let p1 = u1.profile().exec(&mut db).await?.unwrap();
378
379 let u2 = User::create()
380 .name("alice")
381 .profile(Profile::create())
382 .exec(&mut db)
383 .await?;
384 let p2 = u2.profile().exec(&mut db).await?.unwrap();
385
386 let u3 = User::create()
388 .name("bob")
389 .profile(Profile::create())
390 .exec(&mut db)
391 .await?;
392
393 User::filter_by_name("alice")
395 .update()
396 .profile(None)
397 .exec(&mut db)
398 .await?;
399
400 assert_err!(Profile::get_by_id(&mut db, &p1.id).await);
402 assert_err!(Profile::get_by_id(&mut db, &p2.id).await);
403
404 let p3 = u3.profile().exec(&mut db).await?.unwrap();
406 assert_eq!(p3.user_id, u3.id);
407
408 Ok(())
409}
410
411#[driver_test(id(ID))]
412pub async fn unset_has_one_with_required_pair_in_pk_query_update(test: &mut Test) -> Result<()> {
413 #[derive(Debug, toasty::Model)]
414 struct User {
415 #[key]
416 #[auto]
417 id: ID,
418
419 #[has_one]
420 profile: toasty::HasOne<Option<Profile>>,
421 }
422
423 #[derive(Debug, toasty::Model)]
424 struct Profile {
425 #[key]
426 #[auto]
427 id: ID,
428
429 #[unique]
430 user_id: ID,
431
432 #[belongs_to(key = user_id, references = id)]
433 user: toasty::BelongsTo<User>,
434 }
435
436 let mut db = test.setup_db(models!(User, Profile)).await;
437
438 let user = User::create()
439 .profile(Profile::create())
440 .exec(&mut db)
441 .await?;
442 let profile = user.profile().exec(&mut db).await?.unwrap();
443
444 assert_eq!(user.id, profile.user_id);
445
446 User::filter_by_id(user.id)
447 .update()
448 .profile(None)
449 .exec(&mut db)
450 .await?;
451
452 assert_err!(Profile::get_by_id(&mut db, &profile.id).await);
454 Ok(())
455}
456
457#[driver_test(id(ID))]
458pub async fn unset_has_one_with_required_pair_in_non_pk_query_update(
459 test: &mut Test,
460) -> Result<()> {
461 #[derive(Debug, toasty::Model)]
462 struct User {
463 #[key]
464 #[auto]
465 id: ID,
466
467 #[unique]
468 email: String,
469
470 #[has_one]
471 profile: toasty::HasOne<Option<Profile>>,
472 }
473
474 #[derive(Debug, toasty::Model)]
475 struct Profile {
476 #[key]
477 #[auto]
478 id: ID,
479
480 #[unique]
481 user_id: ID,
482
483 #[belongs_to(key = user_id, references = id)]
484 user: toasty::BelongsTo<User>,
485 }
486
487 let mut db = test.setup_db(models!(User, Profile)).await;
488
489 let user = User::create()
490 .email("foo@example.com")
491 .profile(Profile::create())
492 .exec(&mut db)
493 .await?;
494 let profile = user.profile().exec(&mut db).await?.unwrap();
495 assert_eq!(profile.user_id, user.id);
496
497 User::filter_by_email(&user.email)
498 .update()
499 .profile(None)
500 .exec(&mut db)
501 .await?;
502
503 assert_err!(Profile::get_by_id(&mut db, &profile.id).await);
505 Ok(())
506}
507
508#[driver_test(id(ID))]
509pub async fn associate_has_one_by_val_on_insert(test: &mut Test) -> Result<()> {
510 #[derive(Debug, toasty::Model)]
511 struct User {
512 #[key]
513 #[auto]
514 id: ID,
515
516 #[has_one]
517 profile: toasty::HasOne<Profile>,
518 }
519
520 #[derive(Debug, toasty::Model)]
521 struct Profile {
522 #[key]
523 #[auto]
524 id: ID,
525
526 #[unique]
527 user_id: Option<ID>,
528
529 #[belongs_to(key = user_id, references = id)]
530 user: toasty::BelongsTo<Option<User>>,
531
532 bio: String,
533 }
534
535 let mut db = test.setup_db(models!(User, Profile)).await;
536
537 let profile = Profile::create().bio("hello world").exec(&mut db).await?;
539
540 let u1 = User::create().profile(&profile).exec(&mut db).await?;
542
543 let profile_reloaded = u1.profile().exec(&mut db).await?;
544 assert_eq!(profile.id, profile_reloaded.id);
545 assert_eq!(Some(&u1.id), profile_reloaded.user_id.as_ref());
546 assert_eq!(profile.bio, profile_reloaded.bio);
547 Ok(())
548}
549
550#[driver_test(id(ID), scenario(crate::scenarios::has_one_optional_belongs_to))]
551pub async fn associate_has_one_by_val_on_update_query_with_filter_1(test: &mut Test) -> Result<()> {
552 let mut db = setup(test).await;
553
554 let u1 = User::create().name("user 1").exec(&mut db).await?;
555 let p1 = Profile::create().bio("hello world").exec(&mut db).await?;
556
557 User::filter_by_id(u1.id)
559 .update()
560 .profile(&p1)
561 .exec(&mut db)
562 .await?;
563
564 let u1_reloaded = User::get_by_id(&mut db, &u1.id).await?;
565 let p1_reloaded = u1_reloaded.profile().exec(&mut db).await?.unwrap();
566 assert_eq!(p1.id, p1_reloaded.id);
567 assert_eq!(p1.bio, p1_reloaded.bio);
568 assert_eq!(p1_reloaded.user_id.as_ref(), Some(&u1.id));
569
570 User::filter_by_id(u1.id)
572 .update()
573 .profile(None)
574 .exec(&mut db)
575 .await?;
576
577 User::filter_by_id(u1.id)
578 .filter(User::fields().name().eq("anon"))
579 .update()
580 .profile(&p1)
581 .exec(&mut db)
582 .await?;
583
584 let p1_reloaded = Profile::get_by_id(&mut db, &p1.id).await?;
586 assert!(p1_reloaded.user_id.is_none());
587
588 Ok(())
589}
590
591#[driver_test(id(ID), scenario(crate::scenarios::has_one_optional_belongs_to))]
592pub async fn associate_has_one_by_val_on_update_query_with_filter_2(test: &mut Test) -> Result<()> {
593 let mut db = setup(test).await;
594
595 let u1 = toasty::create!(User {
596 name: "User 1",
597 profile: {
598 bio: "hello world"
599 }
600 })
601 .exec(&mut db)
602 .await?;
603
604 let u2 = toasty::create!(User { name: "User 2" })
605 .exec(&mut db)
606 .await?;
607
608 let p1 = u1.profile().exec(&mut db).await?.unwrap();
609 assert_eq!(p1.user_id.as_ref(), Some(&u1.id));
610
611 User::filter_by_id(u2.id)
612 .filter(User::fields().name().eq("anon"))
613 .update()
614 .profile(&p1)
615 .exec(&mut db)
616 .await?;
617
618 let p1_reloaded = Profile::get_by_id(&mut db, &p1.id).await?;
620 assert_eq!(p1_reloaded.user_id.as_ref(), Some(&u1.id));
621
622 Ok(())
623}