オブジェクトの有無によって処理を分岐できるfind_or_initialize_byメソッド

こんにちは!kossyです!



10/25から28まで宮古島に行っており、
ブログの連続更新記録が途絶えてしまいました。

82日間連続で更新できたのは、飽き性の自分にしてみれば
本当にすごいと自画自賛しています笑

今日からまた頑張って更新してみます。





さて、本日はオブジェクトが存在するかによって処理を分岐できる、
find_or_intialize_byメソッドの使い方について、ブログに残してみたいと思います。



環境
Ruby 2.5.1
Rails 5.1.6
MacOS





ユースケース

オブジェクトの有無で作成、取得など処理を分岐させたい場合には
find_or_initialize_byメソッドの出番です。





サンプルコード

モデル: User, Reaction

どのユーザーがどのユーザーにリアクションをしたかを作成する処理です。

def create
  reaction = Reaction.find_or_initialize_by(to_user_id: params[:user_id], from_user_id: current_user.id)
  reaction.update_attributes(status: params[:reaction])
end

引数に指定された要素を使って検索を行います。

今回の場合は、誰に対してリアクションをしたかを表すto_user_idと、
誰がリアクションをしたかを表すfrom_user_idを引数として受け取れるようにしています。

要は、すでにインスタンスが作成されていれば検索して引っかかったインスタンスを返し、
検索の結果、見つからなかった時には新しくインスタンスを作って返しています。

update_attributeメソッドでインスタンスの値を更新する処理をかけています。
このとき、もし新規のインスタンスならば、createが適用されるように勝手に判定してくれているみたいです。




参考にさせていただいた記事
[Rails]find_or_create_byとfind_or_initialize_by – hello-world.jp.net
RailsのActiveRecordでcreate_or_updateを分岐なしでスマートにする方法 - ウェブエンジニア珍道中
first_or_initializeとfind_or_initialize_by - Qiita