以下の記事で 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 を実行しても安全に処理される