toasty_driver_integration_suite/tests/
crud_update_macro.rs1use crate::prelude::*;
2
3#[driver_test(id(ID), scenario(crate::scenarios::two_models))]
5pub async fn update_macro_simple(test: &mut Test) -> Result<()> {
6 let mut db = setup(test).await;
7
8 let mut user = User::create().name("Carl").exec(&mut db).await?;
9
10 toasty::update!(user { name: "Carlos" })
11 .exec(&mut db)
12 .await?;
13
14 assert_eq!(user.name, "Carlos");
15
16 let reloaded = User::get_by_id(&mut db, &user.id).await?;
17 assert_eq!(reloaded.name, "Carlos");
18
19 Ok(())
20}
21
22#[driver_test(id(ID), scenario(crate::scenarios::user_name_email))]
24pub async fn update_macro_multiple_fields(test: &mut Test) -> Result<()> {
25 let mut db = setup(test).await;
26
27 let mut user = User::create()
28 .name("Carl")
29 .email("carl@example.com")
30 .exec(&mut db)
31 .await?;
32
33 toasty::update!(user {
34 name: "Carlos",
35 email: "carlos@example.com",
36 })
37 .exec(&mut db)
38 .await?;
39
40 assert_eq!(user.name, "Carlos");
41 assert_eq!(user.email, "carlos@example.com");
42
43 Ok(())
44}
45
46#[driver_test(id(ID), scenario(crate::scenarios::two_models))]
48pub async fn update_macro_shorthand(test: &mut Test) -> Result<()> {
49 let mut db = setup(test).await;
50
51 let mut user = User::create().name("Carl").exec(&mut db).await?;
52
53 let name = "Carlos";
54 toasty::update!(user { name }).exec(&mut db).await?;
55
56 assert_eq!(user.name, "Carlos");
57
58 Ok(())
59}
60
61#[driver_test(id(ID), scenario(crate::scenarios::two_models))]
64pub async fn update_macro_method_shorthand_set(test: &mut Test) -> Result<()> {
65 let mut db = setup(test).await;
66
67 let mut user = User::create().name("Carl").exec(&mut db).await?;
68
69 toasty::update!(user { name.set("Carlos") })
70 .exec(&mut db)
71 .await?;
72
73 assert_eq!(user.name, "Carlos");
74
75 Ok(())
76}
77
78#[driver_test(id(ID), requires(vec_scalar))]
81pub async fn update_macro_method_shorthand_push(test: &mut Test) -> Result<()> {
82 #[derive(Debug, toasty::Model)]
83 #[allow(dead_code)]
84 struct Item {
85 #[key]
86 #[auto]
87 id: ID,
88 tags: Vec<String>,
89 }
90
91 let mut db = test.setup_db(models!(Item)).await;
92
93 let mut item = toasty::create!(Item {
94 tags: vec!["a".to_string()],
95 })
96 .exec(&mut db)
97 .await?;
98
99 toasty::update!(item { tags.push("b") })
100 .exec(&mut db)
101 .await?;
102
103 assert_eq!(item.tags, vec!["a".to_string(), "b".to_string()]);
104
105 let reloaded = Item::get_by_id(&mut db, &item.id).await?;
106 assert_eq!(reloaded.tags, vec!["a".to_string(), "b".to_string()]);
107
108 Ok(())
109}
110
111#[driver_test(id(ID), requires(vec_scalar))]
114pub async fn update_macro_method_shorthand_extend(test: &mut Test) -> Result<()> {
115 #[derive(Debug, toasty::Model)]
116 #[allow(dead_code)]
117 struct Item {
118 #[key]
119 #[auto]
120 id: ID,
121 tags: Vec<String>,
122 }
123
124 let mut db = test.setup_db(models!(Item)).await;
125
126 let mut item = toasty::create!(Item {
127 tags: vec!["a".to_string()],
128 })
129 .exec(&mut db)
130 .await?;
131
132 toasty::update!(item { tags.extend(["b", "c"]) })
133 .exec(&mut db)
134 .await?;
135
136 let expected = vec!["a".to_string(), "b".to_string(), "c".to_string()];
137 assert_eq!(item.tags, expected);
138
139 let reloaded = Item::get_by_id(&mut db, &item.id).await?;
140 assert_eq!(reloaded.tags, expected);
141
142 Ok(())
143}
144
145#[driver_test(id(ID), requires(vec_pop))]
148pub async fn update_macro_method_shorthand_pop(test: &mut Test) -> Result<()> {
149 #[derive(Debug, toasty::Model)]
150 #[allow(dead_code)]
151 struct Item {
152 #[key]
153 #[auto]
154 id: ID,
155 tags: Vec<String>,
156 }
157
158 let mut db = test.setup_db(models!(Item)).await;
159
160 let mut item = toasty::create!(Item {
161 tags: vec!["a".to_string(), "b".to_string(), "c".to_string()],
162 })
163 .exec(&mut db)
164 .await?;
165
166 toasty::update!(item { tags.pop() }).exec(&mut db).await?;
167
168 let expected = vec!["a".to_string(), "b".to_string()];
169 assert_eq!(item.tags, expected);
170
171 let reloaded = Item::get_by_id(&mut db, &item.id).await?;
172 assert_eq!(reloaded.tags, expected);
173
174 Ok(())
175}
176
177#[driver_test(id(ID), requires(vec_scalar))]
180pub async fn update_macro_method_shorthand_clear(test: &mut Test) -> Result<()> {
181 #[derive(Debug, toasty::Model)]
182 #[allow(dead_code)]
183 struct Item {
184 #[key]
185 #[auto]
186 id: ID,
187 tags: Vec<String>,
188 }
189
190 let mut db = test.setup_db(models!(Item)).await;
191
192 let mut item = toasty::create!(Item {
193 tags: vec!["a".to_string(), "b".to_string()],
194 })
195 .exec(&mut db)
196 .await?;
197
198 toasty::update!(item { tags.clear() }).exec(&mut db).await?;
199
200 assert!(item.tags.is_empty());
201
202 let reloaded = Item::get_by_id(&mut db, &item.id).await?;
203 assert!(reloaded.tags.is_empty());
204
205 Ok(())
206}
207
208#[driver_test(id(ID), scenario(crate::scenarios::user_with_active))]
212pub async fn update_macro_value_reads_target_field(test: &mut Test) -> Result<()> {
213 let mut db = setup(test).await;
214
215 let mut user = toasty::create!(User {
216 name: "Carl",
217 age: 30,
218 active: false,
219 })
220 .exec(&mut db)
221 .await?;
222
223 toasty::update!(user {
224 active: !user.active,
225 age: user.age + 1,
226 })
227 .exec(&mut db)
228 .await?;
229
230 assert_struct!(user, _ { active: true, age: 31, .. });
231
232 let reloaded = User::get_by_id(&mut db, &user.id).await?;
233 assert_struct!(reloaded, _ { active: true, age: 31, .. });
234
235 Ok(())
236}
237
238#[driver_test(id(ID), scenario(crate::scenarios::two_models))]
241pub async fn update_macro_method_shorthand_reads_target_field(test: &mut Test) -> Result<()> {
242 let mut db = setup(test).await;
243
244 let mut user = User::create().name("carl").exec(&mut db).await?;
245
246 toasty::update!(user { name.set(user.name.to_uppercase()) })
247 .exec(&mut db)
248 .await?;
249
250 assert_eq!(user.name, "CARL");
251
252 Ok(())
253}
254
255#[driver_test(id(ID), scenario(crate::scenarios::two_models))]
257pub async fn update_macro_query_target(test: &mut Test) -> Result<()> {
258 let mut db = setup(test).await;
259 let user = User::create().name("Alice").exec(&mut db).await?;
260
261 toasty::update!(User::filter_by_id(user.id) { name: "Bob" })
262 .exec(&mut db)
263 .await?;
264
265 let reloaded = User::get_by_id(&mut db, &user.id).await?;
266 assert_eq!(reloaded.name, "Bob");
267
268 Ok(())
269}
270
271#[driver_test(id(ID))]
274pub async fn update_macro_embedded_patch(test: &mut Test) -> Result<()> {
275 #[derive(Debug, toasty::Embed)]
276 #[allow(dead_code)]
277 struct Metadata {
278 version: i64,
279 status: String,
280 }
281
282 #[derive(Debug, toasty::Model)]
283 #[allow(dead_code)]
284 struct Document {
285 #[key]
286 #[auto]
287 id: ID,
288 title: String,
289 meta: Metadata,
290 }
291
292 let mut db = test.setup_db(models!(Document)).await;
293
294 let mut doc = toasty::create!(Document {
295 title: "Doc",
296 meta: Metadata {
297 version: 1,
298 status: "draft".to_string(),
299 },
300 })
301 .exec(&mut db)
302 .await?;
303
304 toasty::update!(doc {
305 meta: { version: 2, status: "published" },
306 })
307 .exec(&mut db)
308 .await?;
309
310 let reloaded = Document::get_by_id(&mut db, &doc.id).await?;
311 assert_eq!(reloaded.meta.version, 2);
312 assert_eq!(reloaded.meta.status, "published");
313
314 Ok(())
315}
316
317#[driver_test(id(ID), scenario(crate::scenarios::has_many_belongs_to))]
321pub async fn update_macro_has_many_insert(test: &mut Test) -> Result<()> {
322 let mut db = setup(test).await;
323
324 let mut user = User::create().name("Alice").exec(&mut db).await?;
325
326 toasty::update!(user {
327 todos: [{ title: "buy milk" }, { title: "walk dog" }],
328 })
329 .exec(&mut db)
330 .await?;
331
332 let mut titles: Vec<_> = user
333 .todos()
334 .exec(&mut db)
335 .await?
336 .into_iter()
337 .map(|t| t.title)
338 .collect();
339 titles.sort();
340 assert_eq!(titles, ["buy milk", "walk dog"]);
341
342 Ok(())
343}
344
345#[driver_test(id(ID), scenario(crate::scenarios::has_many_belongs_to))]
349pub async fn update_macro_has_many_mixed_list(test: &mut Test) -> Result<()> {
350 let mut db = setup(test).await;
351
352 let mut user = User::create().name("Alice").exec(&mut db).await?;
353 let old = user.todos().create().title("old").exec(&mut db).await?;
354
355 toasty::update!(user {
356 todos: [
357 { title: "new" },
358 toasty::stmt::remove(&old),
359 ],
360 })
361 .exec(&mut db)
362 .await?;
363
364 let titles: Vec<_> = user
365 .todos()
366 .exec(&mut db)
367 .await?
368 .into_iter()
369 .map(|t| t.title)
370 .collect();
371 assert_eq!(titles, ["new"]);
372
373 Ok(())
374}
375
376#[driver_test(id(ID))]
379pub async fn update_macro_mixed_shapes(test: &mut Test) -> Result<()> {
380 #[derive(Debug, toasty::Embed)]
381 #[allow(dead_code)]
382 struct Metadata {
383 version: i64,
384 status: String,
385 }
386
387 #[derive(Debug, toasty::Model)]
388 #[allow(dead_code)]
389 struct Document {
390 #[key]
391 #[auto]
392 id: ID,
393 title: String,
394 meta: Metadata,
395 }
396
397 let mut db = test.setup_db(models!(Document)).await;
398
399 let mut doc = toasty::create!(Document {
400 title: "Doc",
401 meta: Metadata {
402 version: 1,
403 status: "draft".to_string(),
404 },
405 })
406 .exec(&mut db)
407 .await?;
408
409 toasty::update!(doc {
410 title.set("New title"),
411 meta: { version: 2 },
412 })
413 .exec(&mut db)
414 .await?;
415
416 let reloaded = Document::get_by_id(&mut db, &doc.id).await?;
417 assert_eq!(reloaded.title, "New title");
418 assert_eq!(reloaded.meta.version, 2);
419 assert_eq!(reloaded.meta.status, "draft");
421
422 Ok(())
423}