この2つのメソッドは同じような用途で使えますが、どのような使い分けをすればいいのかをまとめてみました。
find_or_initialize_by
# File activerecord/lib/active_record/relation.rb, line 222
def find_or_initialize_by(attributes, &block)
find_by(attributes) || new(attributes, &block)
end
find_by
とnew
の引数に同じattributes
が渡される。
なので、下記のようなJOINしたテーブルを検索条件に含めるとActiveRecord::AssociationTypeMismatch
の例外が発生する。
A.joins(:bs).find_or_initialize_by(bs: {id: 1})
first_or_initialize
# File activerecord/lib/active_record/relation.rb, line 161
def first_or_initialize(attributes = nil, &block)
first || new(attributes, &block)
end
first
がない場合、first_or_initailize
の第一引数でオブジェクトを初期化するので、下記のように検索した条件とは別にAttributeで初期化することができる。
A.where(name: "foo").first_or_initialize(name: "bar")
引数を省略すると、もちらんAttributeはなにも設定されないまま初期化される。
まとめ
-
join
をして、検索条件にjoin
したテーブルが含んでいる場合はfirst_or_initialize
- 検索条件と初期化したいオブジェクトのAttributeと違う場合は
first_or_initialize
、同じ場合はfind_or_initialize_by