2016-09-19 10 views
2

私はRails 3.2からRails 4に移行しました。私はこれを持っていた:未定義のメソッド関係のための `find_or_initialize '

MyModel.find_or_initialize_by_field1("fdsfdsfds") 

今私が持っている今、テスト中に例外が発生し、この

MyModel.where(field1: "fdsfdsfds").find_or_initialize 

undefined method `find_or_initialize' for #<ActiveRecord::Relation []> 

しかしガイドでそれがあるべき他に何について何も言わない

そこ。それを修正するには?返される結果は空の配列であるとき、あなたはそれにfind_or_initalizeメソッドを呼び出すことはできませんので、起こって

+0

自動アップグレードツールのこの結果はありましたか? –

答えて

2

。試してください:

MyModel.where(field1: 'asdfasdfasdf').first_or_initialize 
1

MyModel.where(field1: "fdsfdsfds")多くの点で配列のように動作するコレクションを返します。あなたが.find_or_initialize_byを呼び出したい場合は、ハッシュを渡す:

MyModel.find_or_initialize_by(field1: "fdsfdsfds") 

古い.something_by_attr(x)メソッドの多くは、あなたが言及.something_by(attr: x)

0

彼らは似てますが、二つの方法で同じようにきれいに表現することができ、find_or_initialize_by_Xfind_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(...).firstfind_byによって生成SELECTよりも遅くなり、主キー、順SQLになります:等しい、あなたはパフォーマンス上の理由からwhere(...).firstパターンの上find_byを使用する必要があります。

関連する問題