2009-06-28 9 views
0

Ruby on Railsに問題があります。 私はいくつかの一般的な振る舞いを持つために同じクラスから継承するいくつかのモデルクラスを持っています。Rubyでの継承と多相の競合

親クラスはCachedElementと呼ばれます。 子供の1人はアウトカムと呼ばれます。

CachedElementの任意の子に属するフローという別のモデルが必要です。 Flowには、elementという名前の多態性属性があります。それは属する名前の要素です。

「結果」の代わりに、 。

私は異なるテーブルに格納されているいくつかのタイプのCachedElementを持っているので、element_idはいくつかの異なる要素を参照するので、これは混乱します。

要するに、element_typeフィールドに、親クラス名ではなく子クラス名を参照してください。

どうすればいいですか?

答えて

5

フィールドelement_typeが親クラスに設定されています。これは、ActiveRecordでは、他のモデルから派生するときに単一テーブルの継承を使用することが必要なためです。各インスタンスが格納されているテーブルを参照するため、フィールドはベースクラスを参照します。

CachedElementの子がそれぞれのテーブルに格納されている場合は、継承の使用を使用Rubyモジュールのクラス間でロジックを共有するための標準的なアプローチは、継承の代わりにミックスインを使用することです。たとえば:あなたはすでにやっているよう

module Cacheable 
    # methods that should be available for all cached models 
    # ... 
end 

class Outcome < ActiveRecord::Base 
    include Cacheable 
    # ... 
end 

あなたは簡単に多型の関連付けを使用することができ、そしてelement_typeは、適切なクラスに設定されます。

+0

おかげで、それは私がやったことだが、それはそれは私がやったことだ、モジュールからのメッセージのための – Arthur

1

おかげで、それは私がやったことだが、それは一種のトリッキーなモジュールから両方のインスタンスとクラスメソッドを継承することができるように

クラスメソッドを行うことができることであった。

module Cachable 
    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    module ClassMethods 
    def a_class_method 
     "I'm a class method!" 
    end 
    end 

    def an_instance_method 
    "I'm an instance method!" 
    end 
end 

class Outcome < ActiveRecord::Base 
    include Cacheable 
end 
+0

感謝をインスタンスとクラスメソッドの両方を継承することができるように種類のトリッキーでした。 Ruby on Railsプロジェクトでは、このファイルはどこに配置しますか: をapp/modelフォルダ、またはlibフォルダに入れますか? – Arthur

+0

私はレールマスター上のルビーのものではありませんが、libに入れたり、宝石を作りました:-) –

2

ファイルはlibフォルダに移動する必要があります。しかし... あなたは継承の事を同様に行うことができます。

あなたがする必要があるのは、親クラスを抽象クラスとして動作させることです。

# put this in your parent class then try to save a polymorphic item again. 
# and dont forget to reload, (I prefer restart) if your gonna try this in 
# your console. 
def self.abstract_class? 
    true 
end 

とのthatsかなりそれ、これは本当に、実際に文書にし、他のどこにも見つけるのは難しい 私にとってはちょっとunespectedでした。

Kazuyoshi Tlacaelel。

+0

これはレール5時代にも非常に役立ちます:-) –

1

mixin(Module) でクラスメソッドとインスタンスメソッドを追加する場合は、これらを異なるモジュールで抽象化することをお勧めします。

module FakeInheritance 

    def self.included(klass) 
     klass.extend ClassMethods 
     klass.send(:include, InstanceMethods) 
    end 

    module ClassMethods 
     def some_static_method 
     # you dont need to add self's anywhere since they will be merged into the right scope 
     # and that is very cool because your code is more clean! 
     end 
    end 

    module InstanceMethods 
     # methods in here will be accessable only when you create an instance 
    end 
end 

# fake inheritance with static and instance methods 
class CachedElement 
    include FakeInheritance 
end