ActiveRecordのfind_or_initialize_byメソッドにブロックを渡したときの挙動
過去に書いたソースコードを読んでいて、仕様を理解するのに手間取ってハマったので、共有のために記事を書いておきます。
find_or_initialize_byメソッドの例
以下のようなコードを見かけたとします。
user = User.find_or_initialize_by(email: '[email protected]') do |user|
user.last_name = 'サンプル'
user.first_name = '太郎'
end
上のコードから、どのような仕様を想像するでしょうか?
筆者は、ユーザーが見つかった場合、または、初期化した場合、どちらもlast_name
、first_name
がそれぞれ、サンプル
と 太郎
に初期化されると思ってしまいました。
しかし、実際の挙動としては、以下でした。
ユーザーが見つかった場合は、ブロック内の処理は実行されず、
ユーザーをinitializeした場合は、ブロック内の処理が実行される。
実際に、コードを見てみると、以下のようになっています。
def find_or_initialize_by(attributes, &block)
find_by(attributes) || new(attributes, &block)
end
コードを見ても、上記の挙動が実装されているのが確認でき、find_by
で該当レコードが見つかった場合には、&block
部分が無視されるのが分かります。
本サイトの更新情報は、Twitterの株式会社プレセナ・ストラテジック・パートナーズエンジニア公式アカウントで発信しています。ご確認ください。
最終更新
役に立ちましたか?