4

他のモデルから継承するモデルの関連付けを構築しようとする AR に問題があります。問題は、呼び出しが save メソッドを実行する前に、関連するモデルがデータベースに保存されていることです。

このページで詳細を見つけましたhttp://techspry.com/ruby_and_rails/active-records-or-push-or-concat-method/

それは本当に奇妙です。なぜ AR は関連付けに追加されたモデルを ( << メソッドで) 自動的に保存するのでしょうか? 親がすでに存在する場合でも、save メソッドを呼び出す必要があることは明らかです。この呼び出しを防ぐことができます

@user.reviews.build(good_params)

しかし、これは関連付けに階層があるコンテキストでは問題になります。たとえば、Hunter が :animals を多く持っていて、Dog と Cat が Animal を継承している場合、これを行うことはできません。

@hunter.dogs.build
@hunter.cats.build 

代わりに、私たちは立ち往生しています

@hunter.animals << Cat.new
@hunter.animals << Dog.new 

Cat/Dog クラスに検証がない場合、オブジェクトは自動的にデータベースに保存されます。この動作を防ぐにはどうすればよいですか?

4

2 に答える 2

9

Rails 3 は STI との関連付けを完全にはサポートしておらず、通常はハックが必要であることがわかりました。詳細については、この投稿http://simple10.com/rails-3-sti/を参照してください。コメントの 1 つで述べたように、この問題は Rails 4 で言及されています https://github.com/rails/rails/commit/89b5b31cc4f8407f648a2447665ef23f9024e8a5

その間、私はこの醜い回避策を使用しています:

animal = @hunter.animals.build type: 'Dog' 

次に、構築されたオブジェクトを置き換えます。このステップは、ワークアウトへの反映に必要な場合があります(ルーシーの回答とコメントを確認してください)

hunter.animals[@hunter.animals.index(animal)] = animal.becomes(Dog)

これは、このコンテキストでは正しく動作します。

hunter.animals[@hunter.animals.index(animal)].is_a? Dog

true を返し、代入によるデータベース呼び出しは行われません

于 2013-03-07T10:45:19.367 に答える
5

Gus の回答に基づいて、同様のソリューションを実装しました。

# instantiate a dog object
dog = Dog.new(name: 'fido')

# get the attributes from the dog, add the class (per Gus's answer)
dog_attributes = dog.attributes.merge(type: 'Dog')

# build a new dog using the correct attributes, including the type
hunter.animals.build(dog_attributes)

元の犬のオブジェクトが破棄されていることに注意してください。設定する必要がある属性の数によっては、次のほうが簡単な場合があります。

hunter.animals.build(type: 'Dog', name: 'Fido')
于 2014-04-08T06:59:50.840 に答える