8
1

More than 3 years have passed since last update.

`create_or_find_by` はユニーク制約が定義されたテーブルで効いてくる

Posted at

以下の記事で find_or_create_bycreate_or_find_by の違いについてコメントしたのですが、投稿元の方から反応が無かったので別記事として投稿することにしました :pray:

「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 の場合

正常系

  1. find_by を実行し、レコードが取得できなかった
  2. create を実行し、レコードが作成される

異常系

処理 A と B が同時に実行されている場合

  1. A: find_by を実行し、レコードが取得できなかった
  2. B: A と同じ条件で find_or_create_by を実行。find_by でレコードが取得できなかった
  3. A: create を実行し、レコードが作成される
  4. B: create を実行し、レコードが作成される (実際には unique 制約でエラーになるはず)

同じレコードが 2 つ出来てしまった! (実際には unique 制約でエラーになるはず)

find_or_create_byfindcreate の間に別のプロセスの create が割り込む可能性があります。

create_or_find_by の場合

処理 A と B が同時に実行されている場合

  1. A: create を実行し、レコードが作成される
  2. B: A と同じ条件で create_or_find_by を実行。 create で DB の unique によりレコードの作成に失敗
  3. B: find_by を実行し、レコードが取得される

▶ 別のプロセスが同時に create_or_find_by を実行しても安全に処理される

8
1
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
8
1