0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GORM の FirstOrCreate の Attrs と Assign の使い分け

Last updated at Posted at 2025-06-24

課題:FirstOrCreate で追加フィールドを設定したい

FirstOrCreate で新規作成時に追加のフィールドを設定する場合、AttrsAssign の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 処理を実装できます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?