以下の記事で find_or_create_by
と create_or_find_by
の違いについてコメントしたのですが、投稿元の方から反応が無かったので別記事として投稿することにしました
「find_or_create_by」と「create_or_find_by」 の違い #Railsのコードを読んでみた - Qiita
find_or_create_by でできないカラムもcreate_or_find_byではできてしまう可能性があります。
例えば、Userモデルがあったとします。create_or_find_by ではcreateが先に実行されるため2つ同じようなデータが作られます。
find_or_create_byでは、findが先に実行されるため、検索結果が返され、同じデータは2つ作られることはありません。
意識して使用しないとそのような動作になってしまうのですが、恐らく create_or_find_by
のユースケースは DB で unique 制約が定義されたカラムに対しての実行だと思います。
See also: 新メソッド: #create_or_find_by
find_or_create_by
の場合
正常系
-
find_by
を実行し、レコードが取得できなかった -
create
を実行し、レコードが作成される
異常系
処理 A と B が同時に実行されている場合
- A:
find_by
を実行し、レコードが取得できなかった - B: A と同じ条件で
find_or_create_by
を実行。find_by
でレコードが取得できなかった - A:
create
を実行し、レコードが作成される - B:
create
を実行し、レコードが作成される (実際には unique 制約でエラーになるはず)
同じレコードが 2 つ出来てしまった! (実際には unique 制約でエラーになるはず)
▶ find_or_create_by
の find
と create
の間に別のプロセスの create
が割り込む可能性があります。
create_or_find_by
の場合
処理 A と B が同時に実行されている場合
- A:
create
を実行し、レコードが作成される - B: A と同じ条件で
create_or_find_by
を実行。create
で DB の unique によりレコードの作成に失敗 - B:
find_by
を実行し、レコードが取得される
▶ 別のプロセスが同時に create_or_find_by
を実行しても安全に処理される