彼らは似てますが、二つの方法で同じようにきれいに表現することができ、find_or_initialize_by_X
とfind_or_initialize
は、非常に異なっています。
find_or_initialize_by_
タイプのメソッドは、サブクラスActiveRecord::Base
で定義されたファインダ、つまりアクティブレコードモデルです。単一のレコードを返します。クエリ条件に一致しないレコードがあれば、新しいインスタンスを返します。
find_or_initialze
メソッドはモデルクラス(MyModel
)ではなく、(エラーが意味するように)ActiveRecord::Relation
で呼び出されています。これは、where
と呼ぶと、得られる結果は配列でもレコードでもなく、リレーションであるからです。
配列とリレーションシップは似ていますが、実際にSQLを実行してオブジェクトを作成することを意味するため、実際に実行する必要がある場合にのみパフォーマンスが重視されるため、結果を検査する。
find_or_initialize
への2回目の呼び出しでの問題は、ActiveRecord::Relation
にはfind_or_initialize
メソッドがありません。それはfirst_or_initialize
メソッドを持っています。 (上記の場合、結果セットが空であるということとは関係ありません)first_or_initialize
は、リレーションの最初の結果をフェッチします。または、結果が空の場合は新しいモデルを初期化します。
だから、短い答えはあなただけで呼び出す必要がある:MyModel.where(field1: 'foo').first_or_initialize
を。
他の回答で述べたように、しかし関係、例えばを使用せずに同じことを行うために他の方法があります。
MyMode.find_or_initialize_by(field1: "foo")
これは、あなたがRailsの3.2で使用find_or_initialize_by_X
に近い、実際に他のすべてのwhere(...).first
がfind_by
によって生成SELECT
よりも遅くなり、主キー、順SQLになります:等しい、あなたはパフォーマンス上の理由からwhere(...).first
パターンの上find_by
を使用する必要があります。
自動アップグレードツールのこの結果はありましたか? –