toasty_driver_integration_suite/tests/
select_projection_has_many.rs1use crate::prelude::*;
11
12#[driver_test(id(ID), requires(sql))]
13pub async fn select_has_many_basic(t: &mut Test) -> Result<()> {
14 #[derive(Debug, toasty::Model)]
15 struct User {
16 #[key]
17 #[auto]
18 id: ID,
19 name: String,
20
21 #[has_many]
22 posts: toasty::HasMany<Post>,
23 }
24
25 #[derive(Debug, toasty::Model)]
26 struct Post {
27 #[key]
28 #[auto]
29 id: ID,
30 title: String,
31
32 #[index]
33 user_id: ID,
34
35 #[belongs_to(key = user_id, references = id)]
36 user: toasty::BelongsTo<User>,
37 }
38
39 let mut db = t.setup_db(models!(User, Post)).await;
40
41 toasty::create!(User {
42 name: "Alice",
43 posts: [Post::create().title("alpha"), Post::create().title("beta"),],
44 })
45 .exec(&mut db)
46 .await?;
47
48 let posts_per_user: Vec<Vec<Post>> = User::all()
49 .select(User::fields().posts())
50 .exec(&mut db)
51 .await?;
52
53 assert_eq!(posts_per_user.len(), 1);
54 let mut titles: Vec<String> = posts_per_user[0].iter().map(|p| p.title.clone()).collect();
55 titles.sort();
56 assert_eq!(titles, vec!["alpha".to_string(), "beta".to_string()]);
57
58 Ok(())
59}
60
61#[driver_test(id(ID), requires(sql))]
62pub async fn select_has_many_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_many]
71 posts: toasty::HasMany<Post>,
72 }
73
74 #[derive(Debug, toasty::Model)]
75 struct Post {
76 #[key]
77 #[auto]
78 id: ID,
79 title: String,
80
81 #[index]
82 user_id: ID,
83
84 #[belongs_to(key = user_id, references = id)]
85 user: toasty::BelongsTo<User>,
86 }
87
88 let mut db = t.setup_db(models!(User, Post)).await;
89
90 toasty::create!(User {
91 name: "Alice",
92 posts: [Post::create().title("alpha")],
93 })
94 .exec(&mut db)
95 .await?;
96 toasty::create!(User {
97 name: "Bob",
98 posts: [
99 Post::create().title("beta one"),
100 Post::create().title("beta two"),
101 ],
102 })
103 .exec(&mut db)
104 .await?;
105
106 let posts_per_user: Vec<Vec<Post>> = User::filter(User::fields().name().eq("Bob"))
107 .select(User::fields().posts())
108 .exec(&mut db)
109 .await?;
110
111 assert_eq!(posts_per_user.len(), 1);
112 let mut titles: Vec<String> = posts_per_user[0].iter().map(|p| p.title.clone()).collect();
113 titles.sort();
114 assert_eq!(titles, vec!["beta one".to_string(), "beta two".to_string()]);
115
116 Ok(())
117}
118
119#[driver_test(id(ID), requires(sql))]
120pub async fn select_has_many_first(t: &mut Test) -> Result<()> {
121 #[derive(Debug, toasty::Model)]
122 struct User {
123 #[key]
124 #[auto]
125 id: ID,
126 name: String,
127
128 #[has_many]
129 posts: toasty::HasMany<Post>,
130 }
131
132 #[derive(Debug, toasty::Model)]
133 struct Post {
134 #[key]
135 #[auto]
136 id: ID,
137 title: String,
138
139 #[index]
140 user_id: ID,
141
142 #[belongs_to(key = user_id, references = id)]
143 user: toasty::BelongsTo<User>,
144 }
145
146 let mut db = t.setup_db(models!(User, Post)).await;
147
148 toasty::create!(User {
149 name: "Alice",
150 posts: [Post::create().title("alpha"), Post::create().title("beta"),],
151 })
152 .exec(&mut db)
153 .await?;
154
155 let posts: Option<Vec<Post>> = User::filter(User::fields().name().eq("Alice"))
156 .select(User::fields().posts())
157 .first()
158 .exec(&mut db)
159 .await?;
160
161 let posts = posts.expect("first() returned None for a matching user");
162 let mut titles: Vec<String> = posts.iter().map(|p| p.title.clone()).collect();
163 titles.sort();
164 assert_eq!(titles, vec!["alpha".to_string(), "beta".to_string()]);
165
166 Ok(())
167}