この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