1use crate::prelude::*;
2
3#[driver_test(id(ID))]
6pub async fn deferred_embed_struct(t: &mut Test) -> Result<()> {
7 #[derive(Debug, toasty::Embed)]
8 struct Metadata {
9 author: String,
10 notes: String,
11 }
12
13 #[derive(Debug, toasty::Model)]
14 struct Document {
15 #[key]
16 #[auto]
17 id: ID,
18
19 title: String,
20
21 #[deferred]
22 metadata: toasty::Deferred<Metadata>,
23 }
24
25 let mut db = t.setup_db(models!(Document, Metadata)).await;
26
27 let created = toasty::create!(Document {
28 title: "Hello".to_string(),
29 metadata: Metadata {
30 author: "Alice".to_string(),
31 notes: "Important".to_string(),
32 },
33 })
34 .exec(&mut db)
35 .await?;
36
37 assert_eq!("Hello", created.title);
40 assert_eq!("Alice", created.metadata.get().author);
41 assert_eq!("Important", created.metadata.get().notes);
42
43 let read = Document::filter_by_id(created.id).get(&mut db).await?;
45 assert_eq!("Hello", read.title);
46 assert!(read.metadata.is_unloaded());
47
48 let metadata: Metadata = read.metadata().exec(&mut db).await?;
50 assert_eq!("Alice", metadata.author);
51 assert_eq!("Important", metadata.notes);
52 assert!(read.metadata.is_unloaded());
54
55 let read_with = Document::filter_by_id(created.id)
57 .include(Document::fields().metadata())
58 .get(&mut db)
59 .await?;
60 assert!(!read_with.metadata.is_unloaded());
61 assert_eq!("Alice", read_with.metadata.get().author);
62 assert_eq!("Important", read_with.metadata.get().notes);
63
64 Ok(())
65}
66
67#[driver_test(id(ID))]
81pub async fn deferred_inside_embed_in_enum_variant(t: &mut Test) -> Result<()> {
82 #[derive(Debug, toasty::Embed)]
83 struct Metadata {
84 author: String,
85
86 #[deferred]
87 notes: toasty::Deferred<String>,
88 }
89
90 #[derive(Debug, toasty::Embed)]
91 enum ContactInfo {
92 Email { address: String, metadata: Metadata },
93 Phone { number: String },
94 }
95
96 #[derive(Debug, toasty::Model)]
97 struct Person {
98 #[key]
99 #[auto]
100 id: ID,
101
102 name: String,
103
104 contact: ContactInfo,
105 }
106
107 let mut db = t.setup_db(models!(Person, ContactInfo, Metadata)).await;
108
109 let created = toasty::create!(Person {
112 name: "Alice".to_string(),
113 contact: ContactInfo::Email {
114 address: "alice@example.com".to_string(),
115 metadata: Metadata {
116 author: "Alice".to_string(),
117 notes: "Important".to_string().into(),
118 },
119 },
120 })
121 .exec(&mut db)
122 .await?;
123
124 let ContactInfo::Email {
125 address, metadata, ..
126 } = &created.contact
127 else {
128 panic!("expected Email variant");
129 };
130 assert_eq!("alice@example.com", address);
131 assert_eq!("Alice", metadata.author);
132 assert_eq!("Important", metadata.notes.get());
133
134 let read = Person::filter_by_id(created.id).get(&mut db).await?;
137 let ContactInfo::Email { metadata, .. } = &read.contact else {
138 panic!("expected Email variant");
139 };
140 assert_eq!("Alice", metadata.author);
141 assert!(metadata.notes.is_unloaded());
142
143 Ok(())
144}
145
146#[driver_test(id(ID))]
153pub async fn include_deferred_inside_embed_in_enum_variant(t: &mut Test) -> Result<()> {
154 #[derive(Debug, toasty::Embed)]
155 struct Metadata {
156 author: String,
157
158 #[deferred]
159 notes: toasty::Deferred<String>,
160 }
161
162 #[derive(Debug, toasty::Embed)]
163 enum ContactInfo {
164 Email { address: String, metadata: Metadata },
165 Phone { number: String },
166 }
167
168 #[derive(Debug, toasty::Model)]
169 struct Person {
170 #[key]
171 #[auto]
172 id: ID,
173
174 name: String,
175
176 contact: ContactInfo,
177 }
178
179 let mut db = t.setup_db(models!(Person, ContactInfo, Metadata)).await;
180
181 let alice = toasty::create!(Person {
182 name: "Alice".to_string(),
183 contact: ContactInfo::Email {
184 address: "alice@example.com".to_string(),
185 metadata: Metadata {
186 author: "Alice".to_string(),
187 notes: "Important".to_string().into(),
188 },
189 },
190 })
191 .exec(&mut db)
192 .await?;
193
194 let bob = toasty::create!(Person {
197 name: "Bob".to_string(),
198 contact: ContactInfo::Phone {
199 number: "555-0100".to_string(),
200 },
201 })
202 .exec(&mut db)
203 .await?;
204
205 let alice_read = Person::filter_by_id(alice.id)
207 .include(Person::fields().contact().email().metadata().notes())
208 .get(&mut db)
209 .await?;
210 let ContactInfo::Email { metadata, .. } = &alice_read.contact else {
211 panic!("expected Email variant");
212 };
213 assert_eq!("Alice", metadata.author);
214 assert!(!metadata.notes.is_unloaded());
215 assert_eq!("Important", metadata.notes.get());
216
217 let bob_read = Person::filter_by_id(bob.id)
220 .include(Person::fields().contact().email().metadata().notes())
221 .get(&mut db)
222 .await?;
223 let ContactInfo::Phone { number } = &bob_read.contact else {
224 panic!("expected Phone variant");
225 };
226 assert_eq!("555-0100", number);
227
228 Ok(())
229}
230
231#[driver_test(id(ID))]
234pub async fn deferred_embed_unit_enum(t: &mut Test) -> Result<()> {
235 #[derive(Debug, PartialEq, toasty::Embed)]
236 enum Status {
237 Draft,
238 Published,
239 Archived,
240 }
241
242 #[derive(Debug, toasty::Model)]
243 struct Document {
244 #[key]
245 #[auto]
246 id: ID,
247
248 title: String,
249
250 #[deferred]
251 status: toasty::Deferred<Status>,
252 }
253
254 let mut db = t.setup_db(models!(Document, Status)).await;
255
256 let created = toasty::create!(Document {
257 title: "Hello".to_string(),
258 status: Status::Published,
259 })
260 .exec(&mut db)
261 .await?;
262
263 assert_eq!(&Status::Published, created.status.get());
264
265 let read = Document::filter_by_id(created.id).get(&mut db).await?;
266 assert!(read.status.is_unloaded());
267
268 let status: Status = read.status().exec(&mut db).await?;
269 assert_eq!(Status::Published, status);
270
271 let inc = Document::filter_by_id(created.id)
272 .include(Document::fields().status())
273 .get(&mut db)
274 .await?;
275 assert!(!inc.status.is_unloaded());
276 assert_eq!(&Status::Published, inc.status.get());
277
278 Ok(())
279}
280
281#[driver_test(id(ID))]
284pub async fn deferred_embed_data_enum(t: &mut Test) -> Result<()> {
285 #[derive(Debug, PartialEq, toasty::Embed)]
286 enum ContactInfo {
287 Email { address: String },
288 Phone { number: String },
289 Mail,
290 }
291
292 #[derive(Debug, toasty::Model)]
293 struct Person {
294 #[key]
295 #[auto]
296 id: ID,
297
298 name: String,
299
300 #[deferred]
301 contact: toasty::Deferred<ContactInfo>,
302 }
303
304 let mut db = t.setup_db(models!(Person, ContactInfo)).await;
305
306 let alice = toasty::create!(Person {
307 name: "Alice".to_string(),
308 contact: ContactInfo::Email {
309 address: "alice@example.com".to_string(),
310 },
311 })
312 .exec(&mut db)
313 .await?;
314
315 let bob = toasty::create!(Person {
316 name: "Bob".to_string(),
317 contact: ContactInfo::Mail,
318 })
319 .exec(&mut db)
320 .await?;
321
322 assert_eq!(
323 &ContactInfo::Email {
324 address: "alice@example.com".to_string()
325 },
326 alice.contact.get()
327 );
328
329 let read = Person::filter_by_id(alice.id).get(&mut db).await?;
330 assert!(read.contact.is_unloaded());
331
332 let contact: ContactInfo = read.contact().exec(&mut db).await?;
333 assert_eq!(
334 ContactInfo::Email {
335 address: "alice@example.com".to_string()
336 },
337 contact
338 );
339
340 let read_bob = Person::filter_by_id(bob.id).get(&mut db).await?;
341 let contact: ContactInfo = read_bob.contact().exec(&mut db).await?;
342 assert_eq!(ContactInfo::Mail, contact);
343
344 let inc = Person::filter_by_id(alice.id)
345 .include(Person::fields().contact())
346 .get(&mut db)
347 .await?;
348 assert!(!inc.contact.is_unloaded());
349 assert_eq!(
350 &ContactInfo::Email {
351 address: "alice@example.com".to_string()
352 },
353 inc.contact.get()
354 );
355
356 Ok(())
357}
358
359#[driver_test(id(ID))]
362pub async fn deferred_embed_update_reloads(t: &mut Test) -> Result<()> {
363 #[derive(Debug, toasty::Embed)]
364 struct Metadata {
365 author: String,
366 notes: String,
367 }
368
369 #[derive(Debug, toasty::Model)]
370 struct Document {
371 #[key]
372 #[auto]
373 id: ID,
374
375 title: String,
376
377 #[deferred]
378 metadata: toasty::Deferred<Metadata>,
379 }
380
381 let mut db = t.setup_db(models!(Document, Metadata)).await;
382
383 let created = toasty::create!(Document {
384 title: "Hello".to_string(),
385 metadata: Metadata {
386 author: "Alice".to_string(),
387 notes: "old".to_string(),
388 },
389 })
390 .exec(&mut db)
391 .await?;
392
393 let mut doc = Document::filter_by_id(created.id).get(&mut db).await?;
394 assert!(doc.metadata.is_unloaded());
395
396 doc.update()
397 .metadata(Metadata {
398 author: "Bob".to_string(),
399 notes: "new".to_string(),
400 })
401 .exec(&mut db)
402 .await?;
403
404 assert!(!doc.metadata.is_unloaded());
406 assert_eq!("Bob", doc.metadata.get().author);
407 assert_eq!("new", doc.metadata.get().notes);
408
409 Ok(())
410}
411
412#[driver_test(id(ID))]
420pub async fn deferred_embed_with_deferred_sub_field(t: &mut Test) -> Result<()> {
421 #[derive(Debug, toasty::Embed)]
422 struct Metadata {
423 author: String,
424
425 #[deferred]
426 notes: toasty::Deferred<String>,
427 }
428
429 #[derive(Debug, toasty::Model)]
430 struct Document {
431 #[key]
432 #[auto]
433 id: ID,
434
435 title: String,
436
437 #[deferred]
438 metadata: toasty::Deferred<Metadata>,
439 }
440
441 let mut db = t.setup_db(models!(Document, Metadata)).await;
442
443 let created = toasty::create!(Document {
444 title: "Hello".to_string(),
445 metadata: Metadata {
446 author: "Alice".to_string(),
447 notes: "Important".to_string().into(),
448 },
449 })
450 .exec(&mut db)
451 .await?;
452
453 assert_eq!("Alice", created.metadata.get().author);
455 assert_eq!("Important", created.metadata.get().notes.get());
456
457 let read = Document::filter_by_id(created.id).get(&mut db).await?;
459 assert!(read.metadata.is_unloaded());
460
461 let inc_outer = Document::filter_by_id(created.id)
464 .include(Document::fields().metadata())
465 .get(&mut db)
466 .await?;
467 assert!(!inc_outer.metadata.is_unloaded());
468 assert_eq!("Alice", inc_outer.metadata.get().author);
469 assert!(inc_outer.metadata.get().notes.is_unloaded());
470
471 let inc_inner = Document::filter_by_id(created.id)
474 .include(Document::fields().metadata().notes())
475 .get(&mut db)
476 .await?;
477 assert!(!inc_inner.metadata.is_unloaded());
478 assert_eq!("Alice", inc_inner.metadata.get().author);
479 assert!(!inc_inner.metadata.get().notes.is_unloaded());
480 assert_eq!("Important", inc_inner.metadata.get().notes.get());
481
482 Ok(())
483}
484
485#[driver_test(id(ID))]
488pub async fn deferred_field_inside_embed(t: &mut Test) -> Result<()> {
489 #[derive(Debug, toasty::Embed)]
490 struct Metadata {
491 author: String,
492
493 #[deferred]
494 notes: toasty::Deferred<String>,
495 }
496
497 #[derive(Debug, toasty::Model)]
498 struct Document {
499 #[key]
500 #[auto]
501 id: ID,
502
503 title: String,
504
505 metadata: Metadata,
506 }
507
508 let mut db = t.setup_db(models!(Document, Metadata)).await;
509
510 let created = toasty::create!(Document {
511 title: "Hello".to_string(),
512 metadata: Metadata {
513 author: "Alice".to_string(),
514 notes: "Important".to_string().into(),
515 },
516 })
517 .exec(&mut db)
518 .await?;
519
520 assert_eq!("Alice", created.metadata.author);
522 assert_eq!("Important", created.metadata.notes.get());
523
524 let read = Document::filter_by_id(created.id).get(&mut db).await?;
526 assert_eq!("Alice", read.metadata.author);
527 assert!(read.metadata.notes.is_unloaded());
528
529 let inc = Document::filter_by_id(created.id)
531 .include(Document::fields().metadata().notes())
532 .get(&mut db)
533 .await?;
534 assert!(!inc.metadata.notes.is_unloaded());
535 assert_eq!("Important", inc.metadata.notes.get());
536
537 Ok(())
538}
539
540#[driver_test(id(ID))]
546pub async fn update_embed_by_value_with_deferred_sub_field(t: &mut Test) -> Result<()> {
547 #[derive(Debug, toasty::Embed)]
548 struct Metadata {
549 author: String,
550
551 #[deferred]
552 notes: toasty::Deferred<String>,
553 }
554
555 #[derive(Debug, toasty::Model)]
556 struct Document {
557 #[key]
558 #[auto]
559 id: ID,
560
561 title: String,
562
563 metadata: Metadata,
564 }
565
566 let mut db = t.setup_db(models!(Document, Metadata)).await;
567
568 let mut doc = toasty::create!(Document {
569 title: "Hello".to_string(),
570 metadata: Metadata {
571 author: "Alice".to_string(),
572 notes: "old".to_string().into(),
573 },
574 })
575 .exec(&mut db)
576 .await?;
577
578 doc.update()
579 .metadata(Metadata {
580 author: "Bob".to_string(),
581 notes: "new".to_string().into(),
582 })
583 .exec(&mut db)
584 .await?;
585
586 assert_eq!("Bob", doc.metadata.author);
588 assert_eq!("new", doc.metadata.notes.get());
589
590 let reread = Document::filter_by_id(doc.id)
593 .include(Document::fields().metadata().notes())
594 .get(&mut db)
595 .await?;
596 assert_eq!("Bob", reread.metadata.author);
597 assert_eq!("new", reread.metadata.notes.get());
598
599 Ok(())
600}