2009-06-28 51 views
0

我在Ruby on Rails上遇到了問題。 我有幾個模型類從相同的類繼承,以便有一些通用的行爲。紅寶石在軌道上的繼承和多態性衝突

父類稱爲CachedElement。 其中一個孩子叫做成果。

我想要一個其他模型,稱爲流屬於CachedElement的任何孩子。 因此,Flow有一個稱爲元素的多態屬性,它屬於__

當我創建一個屬於一個結果的新流程時,element_type被設置爲父類的「CachedElement」,而不是「結果」 。

這很令人困惑,因爲由於我有幾種類型的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 2009-06-29 06:58:40

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 2009-07-05 20:37:03

+0

我不是那種在rails master上的紅寶石,但是我會把它放在lib中或者製作一個gem :-) – 2009-07-06 07:28:29

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 

和多數民衆差不多了,這是有點unespected我居然真的 很難找到的文檔中和其他地方。

Kazuyoshi Tlacaelel。

1

如果你想通過mixin(模塊) 添加類方法和實例方法,那麼我建議你在不同的模塊中抽象這些。

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