Skip to main content

toasty_driver_integration_suite/tests/
select_projection_has_one.rs

1//! `.select(...)` projection through a `HasOne` relation field.
2//!
3//! Per PR #827, projecting a `BelongsTo` works because the macro emits
4//! `IntoExpr<TargetModel>` for the relation field-struct and the lowering
5//! walk routes the reference through `build_relation_subquery`.  `HasOne`
6//! uses the same field-struct type (`<Target as Relation>::OneField`) and
7//! `build_relation_subquery` already has a `HasOne` branch (used by
8//! `.include`), so the case works end-to-end with no further production
9//! code change.
10
11use crate::prelude::*;
12
13#[driver_test(id(ID), requires(sql))]
14pub async fn select_has_one_basic(t: &mut Test) -> Result<()> {
15    #[derive(Debug, toasty::Model)]
16    struct User {
17        #[key]
18        #[auto]
19        id: ID,
20        name: String,
21
22        #[has_one]
23        profile: toasty::HasOne<Profile>,
24    }
25
26    #[derive(Debug, toasty::Model)]
27    struct Profile {
28        #[key]
29        #[auto]
30        id: ID,
31
32        #[unique]
33        user_id: Option<ID>,
34
35        #[belongs_to(key = user_id, references = id)]
36        user: toasty::BelongsTo<Option<User>>,
37
38        bio: String,
39    }
40
41    let mut db = t.setup_db(models!(User, Profile)).await;
42
43    toasty::create!(User {
44        name: "Alice",
45        profile: Profile::create().bio("apple a day"),
46    })
47    .exec(&mut db)
48    .await?;
49
50    let profiles: Vec<Profile> = User::all()
51        .select(User::fields().profile())
52        .exec(&mut db)
53        .await?;
54
55    assert_eq!(profiles.len(), 1);
56    assert_eq!(profiles[0].bio, "apple a day");
57
58    Ok(())
59}
60
61#[driver_test(id(ID), requires(sql))]
62pub async fn select_has_one_with_filter(t: &mut Test) -> Result<()> {
63    #[derive(Debug, toasty::Model)]
64    struct User {
65        #[key]
66        #[auto]
67        id: ID,
68        name: String,
69
70        #[has_one]
71        profile: toasty::HasOne<Profile>,
72    }
73
74    #[derive(Debug, toasty::Model)]
75    struct Profile {
76        #[key]
77        #[auto]
78        id: ID,
79
80        #[unique]
81        user_id: Option<ID>,
82
83        #[belongs_to(key = user_id, references = id)]
84        user: toasty::BelongsTo<Option<User>>,
85
86        bio: String,
87    }
88
89    let mut db = t.setup_db(models!(User, Profile)).await;
90
91    toasty::create!(User {
92        name: "Alice",
93        profile: Profile::create().bio("alpha bio"),
94    })
95    .exec(&mut db)
96    .await?;
97    toasty::create!(User {
98        name: "Bob",
99        profile: Profile::create().bio("beta bio"),
100    })
101    .exec(&mut db)
102    .await?;
103
104    let profiles: Vec<Profile> = User::filter(User::fields().name().eq("Bob"))
105        .select(User::fields().profile())
106        .exec(&mut db)
107        .await?;
108
109    assert_eq!(profiles.len(), 1);
110    assert_eq!(profiles[0].bio, "beta bio");
111
112    Ok(())
113}
114
115#[driver_test(id(ID), requires(sql))]
116pub async fn select_has_one_first(t: &mut Test) -> Result<()> {
117    #[derive(Debug, toasty::Model)]
118    struct User {
119        #[key]
120        #[auto]
121        id: ID,
122        name: String,
123
124        #[has_one]
125        profile: toasty::HasOne<Profile>,
126    }
127
128    #[derive(Debug, toasty::Model)]
129    struct Profile {
130        #[key]
131        #[auto]
132        id: ID,
133
134        #[unique]
135        user_id: Option<ID>,
136
137        #[belongs_to(key = user_id, references = id)]
138        user: toasty::BelongsTo<Option<User>>,
139
140        bio: String,
141    }
142
143    let mut db = t.setup_db(models!(User, Profile)).await;
144
145    toasty::create!(User {
146        name: "Alice",
147        profile: Profile::create().bio("apple a day"),
148    })
149    .exec(&mut db)
150    .await?;
151
152    let profile: Option<Profile> = User::filter(User::fields().name().eq("Alice"))
153        .select(User::fields().profile())
154        .first()
155        .exec(&mut db)
156        .await?;
157
158    assert_eq!(profile.map(|p| p.bio).as_deref(), Some("apple a day"));
159
160    Ok(())
161}