2013-04-20 96 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