1

だから私は最近単一テーブル継承を調べていて、この一般的な質問/回答を見つけました:

質問:STIでBeta <Alphaと仮定して、オブジェクトのクラスをobjAlphaからBetaにどのように変更しますか?

回答:ルビーはダックタイプの言語なので、キャストは使用しません。ただし、必要なのは「type」変数を「Beta」に設定してオブジェクトを保存することだけです。次にAlphaオブジェクトをロードすると、タイプはBetaになります。

obj = Alpha.new
obj.save #now obj is of type Alpha

obj.type = "Beta"
obj.save #now obj is of type Beta

ただし、このアプローチは私にはうまくいかないようです。objは正しく保存されますが、ベータオブジェクトとしてはまったく機能していないようです。ベータ版の検証を実行せずに保存し、チェックobj.respond_to?(:beta_method) #beta_method being a method in the beta classするとfalseが返されました。このアプローチは機能しませんか?正しいアプローチはありますか?それとも私は単に何か間違ったことをしているのですか?

編集

Alpha.last.respond_to(:beta_method)を実行すると、falseが返され、Beta.last.respond_to(:beta_method)がtrueを返すことがわかりました(ただし、Alpha.lastとBeta.lastの両方が同じオブジェクトを返しました)。興味深い開発?それでも、誰かがこれを(rubyが継承を処理する方法に関して)詳細に説明できれば、それは素晴らしいことです。

4

2 に答える 2

4

達成しようとしていることに応じてbecomes、オブジェクトのタイプを使用または変更して(または直接update_attribute)、データベースからリロード(または両方)することができます。

becomes前のオブジェクトと同じ属性を使用して、唯一のパラメータとして渡されたクラスの新しいオブジェクトをインスタンス化して返します。これにより、新しいオブジェクトのメソッドを呼び出すことができます。例えば:

a = Alpha.last

# if you want to save the new type in the database:
a.type = 'Beta' 
a.save

b = a.becomes(Beta)
b.respond_to?(:beta_method)
=> true

メソッドを呼び出す順序が重要であることがわかりました。最初に使用してからbecomesタイプを変更して保存しようとしても、データベースのタイプは変更されません。

于 2011-07-27T19:29:25.377 に答える
1

あなたが言ったように、Rubyは型キャストを許可していません。むしろ、ここで起こっていることは、ActiveRecordがtypeフィールドの値に応じて異なるクラスのインスタンスをインスタンス化しているということです。したがって、「ベータ」に変更する場合、Rubyの観点からは実際には何もしていません。

ただし、ActiveRecordがデータベースを調べてレコードを取得すると、新しい値が表示され、ではなくtypeのインスタンスがインスタンス化されます。このプロセスは、特にActiveRecordよりもRubyとは関係がありません。BetaAlpha

状況によっては、よりエレガントなアプローチが存在する場合があります。モデルをあるタイプから別のタイプに「変換」する必要がある場合(たとえば、anEmployeeがになり、Manager追加のメソッドがあります)、これは合理的な方法です。その他の場合は、ミックスインまたはその他のツールを使用することで、目標をより適切に達成できる可能性があります。

必要に応じて、次のようにBetafromの属性の一時インスタンスを作成することもできます。Alpha

# obj is an instance of Alpha
obj = Beta.new(obj.attributes)

しかし、これはほとんどの場合、同様に行う必要のある奇妙なことです。

于 2011-07-27T18:35:01.033 に答える