Skip to main content

toasty_driver_integration_suite/tests/
select_projection_has_many.rs

1//! `.select(...)` projection through a `HasMany` relation field.
2//!
3//! Field handles for `HasMany` relations return
4//! `<Target as Relation>::ManyField<__Origin>` (the macro-generated
5//! `*FieldList` struct).  An `IntoExpr<List<TargetModel>>` impl on that
6//! struct lets the field handle flow through `.select(...)` the same way
7//! `BelongsTo`/`HasOne` handles do; each parent row projects to a list of
8//! related rows, and the executor decodes the result as `Vec<Vec<Target>>`.
9
10use crate::prelude::*;
11
12#[driver_test(
13    scenario(crate::scenarios::has_many_belongs_to::id_uuid),
14    requires(sql)
15)]
16pub async fn select_has_many(t: &mut Test) -> Result<()> {
17    let mut db = setup(t).await;
18
19    toasty::create!(User {
20        name: "Alice",
21        todos: [Todo::create().title("alpha"), Todo::create().title("beta"),],
22    })
23    .exec(&mut db)
24    .await?;
25
26    let todos_per_user: Vec<Vec<Todo>> = User::all()
27        .select(User::fields().todos())
28        .exec(&mut db)
29        .await?;
30
31    assert_eq!(todos_per_user.len(), 1);
32    let mut titles: Vec<String> = todos_per_user[0].iter().map(|p| p.title.clone()).collect();
33    titles.sort();
34    assert_eq!(titles, vec!["alpha".to_string(), "beta".to_string()]);
35
36    toasty::create!(User {
37        name: "Bob",
38        todos: [
39            Todo::create().title("beta one"),
40            Todo::create().title("beta two"),
41        ],
42    })
43    .exec(&mut db)
44    .await?;
45
46    let todos_per_user: Vec<Vec<Todo>> = User::filter(User::fields().name().eq("Bob"))
47        .select(User::fields().todos())
48        .exec(&mut db)
49        .await?;
50
51    assert_eq!(todos_per_user.len(), 1);
52    let mut titles: Vec<String> = todos_per_user[0].iter().map(|p| p.title.clone()).collect();
53    titles.sort();
54    assert_eq!(titles, vec!["beta one".to_string(), "beta two".to_string()]);
55
56    let todos: Option<Vec<Todo>> = User::filter(User::fields().name().eq("Alice"))
57        .select(User::fields().todos())
58        .first()
59        .exec(&mut db)
60        .await?;
61
62    let todos = todos.expect("first() returned None for a matching user");
63    let mut titles: Vec<String> = todos.iter().map(|p| p.title.clone()).collect();
64    titles.sort();
65    assert_eq!(titles, vec!["alpha".to_string(), "beta".to_string()]);
66
67    Ok(())
68}