2013-04-20 76 views
0

我想我要完成的是多表继承,但我不知道如何正确地实现它。Rails活动模型继承

我想从基类Device开始,它将包含所有常用字段,如名称和启用。

class Device 
    # in app/models 
    # Fields 
    # String name 
    # boolean enabled 
end 

我然后要为不同的设备类型如LightDevice

class Light < ActiveRecord:Base 
    # in app/models 
    # Fields 
    # String type 

    include Device 

    def on 
    raise NotImplementedError 
    end 

    def off 
    raise NotImplementedError 
    end 
end 

继承然后我将具有适用于特定装置如X10LightZWaveLight将定义的类创建抽象类每个设备的具体细节并实现抽象方法。然后

class X10Light < Light 
    # in app/models 
    # Fields 
    # String serial_number 

    def on 
    # fully implemented on method 
    end 

    def off 
    # fully implemented off method 
    end 
end 

我的目标是使用它像下面

light1 = X10Light.new 
light1.serial_number = "x1" 
light1.save 

light2 = ZWaveLight.new 
light2.serial_number = "z1" 
light2.save 

all_lights = Light.all 
all_lights.each do |light| 
    light.off 
end 

我想我已经计划好了的事情,这是可能的方式,但我觉得有一些不正确的执行。我会很感激任何帮助减少这方面的细节。谢谢!

+0

在红宝石中,不要做'def on raise NotImplementedError end' ---而是让你的类不是'respond_to:on'。 – 2013-04-20 18:14:31

回答

0

可以使用单表继承,你需要创建一个模型Device将举行所有字段以及名为type,其中轨道将存储的具体实例的类名保留列。

rails g model Device type:string ... other fields (ie columns for device, light, x10light) ... 

class Device < ActiveRecord:Base 
    ... 
end 

class Light < Device 
    ... 
end 

class X10Light < Light 
    ... 
end 

使用STI的缺点是,你最终会得到一个包含继承树所有列的表。

+0

代表[Niels-b](http://stackoverflow.com/users/1690765/niels-b):您的模型将被自动确定范围,这意味着当您执行Light.all,Rails将在类型等于light的devices表中激发SQL查询。请记住,不会找到子类。所以Light.all将不包含任何X10Light。 – 2013-04-20 17:38:13

+0

其实我必须纠正自己。缺失的子类只是开发中的一个问题。在生产中,Rails预加载所有类并构建一个漂亮的系列树,因此对Light.all的查询实际上会构建一个where子句来查询light和x10light。 – 2013-04-20 17:43:19