rails/activerecord/CHANGELOG.md @ 300d080ada31ac297264e6abba6ca16cd2db5925
を読んでみたので誤訳 & わからない部分は後で調べ直すためのメモ。
find_or_create_by
, find_or_create_by!
, find_or_initialize
が追加されている。
これらのメソッドはfirst_or_create
系のメソッドと似ているが、レコードが作られるときの振る舞いは少し異なっている。
User.Where(firstname: 'Hoge').first_or_create
はスコープのコンテキストで実行されるcreate
コールバックを伴って
User.Where(firstname: 'Hoge').create
を実行する。これは、コールバック内で実行するクエリに影響を及ぼす。
(Whereの結果がcreateに影響するということでいいのかな?)
User.find_or_create(firstname: 'Hoge')
は
User.create(firstname: 'Hoge')
を実行する。これは明らかにコールバック内のクエリのスコープに影響を与えない。(うーん、確かにWhere
が消えたのでWhere
の結果がcreate
のクエリを汚すことはないか。ただ、これだと、find_or_create_by
のfindの意味合いがよくわからないとおもうのだが・・・。あとで調べ直す。)
find_or_create_by
を利用したほうは読みやすく、素直だ。
もし、レコード生成時に追加で必要な属性があるなら、以下の方法のうちどちらかを採用すればいい。
User.create_with(active:true).find_or_create_by(firstname: 'Hoge')
User.find_or_create(firstname: 'Hoge'){|u| u.active = true}
first_or_create
系のメソッドはfind_or_create
のAPIを支持して、nodoc'edとした。first_or_create
系のメソッドはそのうちdeprecatedとなるかもしれないが、これらの実装は少なく、たくさんのうっとうしいdeprecation warningをユーザに出す価値は多分ないでしょう。
("これらの実装は小さく"の部分がわからんなぁ。後で調べ直す。)