課題:FirstOrCreate で追加フィールドを設定したい
FirstOrCreate
で新規作成時に追加のフィールドを設定する場合、Attrs
と Assign
の2つの方法があります。
// 基本形(WHERE条件のフィールドのみ設定される)
user, err := u.WithContext(ctx).Where(u.Email.Eq("user@example.com")).FirstOrCreate()
Attrs, Assign の違い
Attrs - 新規作成時のみ適用
user, err := u.WithContext(ctx).
Attrs(field.Attrs(&model.User{Name: "Default User", Active: true})).
Where(u.Email.Eq("user@example.com")).
FirstOrCreate()
- レコードが存在しない場合: 指定した値で新規作成
- レコードが既に存在する場合: 既存レコードをそのまま返す(Attrsは無視)
Assign - 常に適用(強制更新)
user, err := u.WithContext(ctx).
Assign(field.Attrs(&model.User{LastLoginAt: time.Now()})).
Where(u.Email.Eq("user@example.com")).
FirstOrCreate()
- レコードが存在しない場合: 指定した値で新規作成
- レコードが既に存在する場合: 指定した値で既存レコードを更新
使い分けパターン
用途 | メソッド | 例 |
---|---|---|
デフォルト値・初期設定 | Attrs |
ユーザー設定、テーマ設定 |
アクセス記録・カウンター | Assign |
最終ログイン時刻、アクセス回数 |
// 設定の初期化(既存設定は保持)
userSetting, err := us.WithContext(ctx).
Attrs(field.Attrs(&model.UserSetting{Theme: "light", Language: "ja"})).
Where(us.UserID.Eq(userID)).FirstOrCreate()
// アクセス記録(毎回更新)
accessLog, err := al.WithContext(ctx).
Assign(field.Attrs(&model.AccessLog{LastAccessAt: time.Now()})).
Where(al.UserID.Eq(userID)).FirstOrCreate()
まとめ
- Attrs: 「一度だけ設定したい」デフォルト値に使用
- Assign: 「毎回更新したい」値に使用
適切な使い分けで、データの整合性を保ちながら効率的な FirstOrCreate 処理を実装できます。