Skip to main content

toasty_driver_integration_suite/scenarios/
user_group_membership.rs

1use crate::prelude::*;
2
3scenario! {
4    //! A bidirectional many-to-many relation implemented with a join model.
5    //!
6    //! `User::groups` traverses `Membership::group`, while `Group::users`
7    //! traverses the same rows through `Membership::user`. The composite key
8    //! permits only one membership for each user-group pair. `role` represents
9    //! data stored on the relation itself.
10
11    #[derive(Debug, toasty::Model)]
12    struct User {
13        #[key]
14        #[auto]
15        id: uuid::Uuid,
16
17        name: String,
18
19        #[has_many]
20        memberships: toasty::Deferred<Vec<Membership>>,
21
22        #[has_many(via = memberships.group)]
23        groups: toasty::Deferred<Vec<Group>>,
24    }
25
26    #[derive(Debug, toasty::Model)]
27    struct Group {
28        #[key]
29        #[auto]
30        id: uuid::Uuid,
31
32        name: String,
33
34        #[has_many]
35        memberships: toasty::Deferred<Vec<Membership>>,
36
37        #[has_many(via = memberships.user)]
38        users: toasty::Deferred<Vec<User>>,
39    }
40
41    #[derive(Debug, toasty::Model)]
42    #[key(user_id, group_id)]
43    struct Membership {
44        #[index]
45        user_id: uuid::Uuid,
46
47        #[belongs_to(key = user_id, references = id)]
48        user: toasty::Deferred<User>,
49
50        #[index]
51        group_id: uuid::Uuid,
52
53        #[belongs_to(key = group_id, references = id)]
54        group: toasty::Deferred<Group>,
55
56        role: String,
57    }
58
59    struct Fixture {
60        alice: User,
61        carol: User,
62        rust: Group,
63        empty: Group,
64    }
65
66    async fn setup(test: &mut Test) -> toasty::Db {
67        test.setup_db(models!(User, Group, Membership)).await
68    }
69
70    async fn seed(db: &mut toasty::Db) -> Result<Fixture> {
71        let mut users = toasty::create!(User::[
72            { name: "Alice" },
73            { name: "Bob" },
74            { name: "Carol" },
75        ])
76        .exec(&mut *db)
77        .await?;
78        let alice = users.remove(0);
79        let bob = users.remove(0);
80        let carol = users.remove(0);
81
82        let mut groups = toasty::create!(Group::[
83            { name: "Rust" },
84            { name: "Databases" },
85            { name: "Empty" },
86        ])
87        .exec(&mut *db)
88        .await?;
89        let rust = groups.remove(0);
90        let databases = groups.remove(0);
91        let empty = groups.remove(0);
92
93        toasty::create!(Membership::[
94            { user: &alice, group: &rust,      role: "owner"  },
95            { user: &alice, group: &databases, role: "member" },
96            { user: &bob,   group: &rust,      role: "member" },
97        ])
98        .exec(&mut *db)
99        .await?;
100
101        Ok(Fixture {
102            alice,
103            carol,
104            rust,
105            empty,
106        })
107    }
108}