「find_or_initialize_by」や「find_or_create_by」とは?
Rails4以上で使えるようになったActiveRecordのメソッドです。
find_or_initialize_by
新規作成をして保存しない。既存テーブルにデータがあればfind_byの結果を返してくれて、なければnewしてインスタンスを作ってくれます。
用途
既に保存されているレコードかチェックして除去するために使います。例えば、バッチ処理の一括登録時に少しでも処理の負荷を軽減したりするために使います。
注意点
初期化するのとsave!するのが別に行われているのでもしマルチプロセス環境で並列で動かしている場合はユニーク制約がかかっているプロパティについて同じ値を持ったインスタンスが初期化されてどちらかが先にsave!されるとユニーク制約に引っかかる可能性がある。対策としてはユニーク制約のバリデーションを先に行うようにすると良いでしょう。
find_or_initialize_byの戻り値 = persisted?
データベースの保存状態や真偽値をチェックできます。インスタンスが保存されていないかつ今までに削除されていない時だけtrueを返します。
find_or_initialize_byの戻り値 = new_record?
データベースの保存状態や真偽値をチェックできます。インスタンスが保存されていない時だけtrueを返します。
find_or_create_by
対象を検索してない場合はcreateする。(find_or_initialize_byはnewですがこちらはcreateです。)
新規作成をして保存する。既存テーブルにデータがあればfind_byの結果を返してくれて、なければcreateの結果を返してくれます。
create_or_find_by(Rails6から)
「find_or_create_by」で適切な制約が設定されていない場合に重複エラー(ActiveRecord::RecordNotUnique)が常に発生していました。その対策として出てきたメソッドです。
新規作成(create)のtransactionに失敗(ActiveRecord::RecordNotUnique)したらfind_byします。createが先に実行されるため2つ同じデータが作成されてしまう可能性があるので注意です。
この記事へのコメントはありません。