@@ -10,36 +10,53 @@ import (
1010 "github.com/database-playground/backend-v2/ent/group"
1111 "github.com/database-playground/backend-v2/ent/user"
1212 "github.com/database-playground/backend-v2/internal/useraccount"
13+ "github.com/samber/lo"
1314)
1415
16+ // SeedUsers creates users from the provided seed records.
17+ //
18+ // Each record must contain a valid email and an optional group slug.
19+ // If the referenced group does not exist, an error is returned.
20+ // If a user with the same email already exists, it is skipped without error.
21+ //
22+ // SeedUsers returns an error if validation, group lookup, or user creation fails.
1523func (c * Context ) SeedUsers (ctx context.Context , userSeedRecords []UserSeedRecord ) error {
1624 // validate records
25+ if len (userSeedRecords ) == 0 {
26+ return nil
27+ }
28+
1729 for i , record := range userSeedRecords {
1830 if err := record .Validate (); err != nil {
1931 return fmt .Errorf ("user seed record #%d: %w" , i , err )
2032 }
2133 }
2234
23- // query groups for the records
24- groups := make (map [string ]* ent.Group )
25- for _ , record := range userSeedRecords {
26- group , err := c .entClient .Group .Query ().Where (group .NameEQ (record .GetGroup ())).Only (ctx )
27- if err != nil {
28- if ent .IsNotFound (err ) {
29- return fmt .Errorf ("group %q not found" , record .GetGroup ())
30- }
35+ // collect unique group names
36+ uniqueGroupName := lo .Uniq (lo .Map (userSeedRecords , func (record UserSeedRecord , _ int ) string {
37+ return record .GetGroup ()
38+ }))
3139
32- return fmt .Errorf ("query group %q: %w" , record .GetGroup (), err )
33- }
34- groups [record .GetGroup ()] = group
40+ // query all required groups in a single batch
41+ entGroups , err := c .entClient .Group .Query ().Where (group .NameIn (uniqueGroupName ... )).All (ctx )
42+ if err != nil {
43+ return fmt .Errorf ("query groups: %w" , err )
3544 }
3645
46+ groups := make (map [string ]* ent.Group , len (entGroups ))
47+ for _ , g := range entGroups {
48+ groups [g .Name ] = g
49+ }
50+
51+ // ensure all requested groups were found
52+ for _ , name := range uniqueGroupName {
53+ if _ , ok := groups [name ]; ! ok {
54+ return fmt .Errorf ("group %q not found" , name )
55+ }
56+ }
3757 // create users
3858 for _ , record := range userSeedRecords {
39- group , ok := groups [record .GetGroup ()]
40- if ! ok {
41- return fmt .Errorf ("user record %q: group %q not found" , record .GetEmail (), record .GetGroup ())
42- }
59+ group := groups [record .GetGroup ()]
4360
4461 // check if user already exists
4562 user , err := c .entClient .User .Query ().Where (user .EmailEQ (record .Email )).First (ctx )
@@ -63,15 +80,19 @@ func (c *Context) SeedUsers(ctx context.Context, userSeedRecords []UserSeedRecor
6380 return nil
6481}
6582
83+ // UserSeedRecord represents a user seed record.
6684type UserSeedRecord struct {
6785 Email string `json:"email"`
6886 Group string `json:"group"`
6987}
7088
89+ // GetEmail returns the email of the user seed record.
7190func (r UserSeedRecord ) GetEmail () string {
7291 return r .Email
7392}
7493
94+ // GetGroup returns the group of the user seed record.
95+ // If the group slug is omitted, the user will be added to the `student` group.
7596func (r UserSeedRecord ) GetGroup () string {
7697 if r .Group == "" {
7798 return useraccount .StudentGroupSlug
@@ -80,6 +101,7 @@ func (r UserSeedRecord) GetGroup() string {
80101 return r .Group
81102}
82103
104+ // Validate validates the user seed record.
83105func (r UserSeedRecord ) Validate () error {
84106 if r .Email == "" {
85107 return errors .New ("email is required" )
0 commit comments