2009-06-28 54 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