Rails4以上で使える `find_or_create_by` `find_or_initialize_by` が便利


たまたまAPIリファレンス見ていたら気づいた!

find_or_create_byfind_or_initialize_by
http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-find_or_create_by

メソッド名その名の通りの挙動になると想像できると思うが、引数に渡した条件により、フィルタリングされ、ブロックにより必要な値をセットすることで createinitialize する時の初期値が設定できる。

サンプル
# first_nameが abc のデータがあれば find される
# first_nameが abc のデータが無ければ、first_name: 'abc'、last_name: "123" が入ったユーザがcreateされる。
User.find_or_create_by(first_name: 'abc') do |user|
  user.last_name = '123'
end

# メソッドの引数に複数を設定するとfind_by時の条件が AND での複数条件検索となる。
User.find_or_create_by(first_name: 'abc', group_id: 3) do |user|
  user.last_name = '123'
end

ユースケース

oauthで認証時にユーザ新規登録なのか、既存ユーザなのか判定する処理とかでうまく使えそう

oauth認証で帰ってくるコールバックのコントローラから以下の find_or_create_with_oauth メソッドを呼び出す。

oauthのサンプル
# 動作するか未保証
class User < ActiveRecord::Base
  def self.find_or_create_with_oauth(oauth)
    User.find_or_create_by(uid: oauth['uid']) do |user|
      user.name = oauth['name']
      user.provider = oauth['provider']
      user.uid = oauth['uid']
    end
  end
end

以上。