2014-08-31 49 views
1

假設我創建一個簡單的特性的模型:(Rails)我如何繞過STI空字段?

class CreateWingedThings < ActiveRecord::Migration 
    create_table :winged_things do 
    t.integer :number_of_wings 
    t.integer :species 
    t.integer :air_speed_velocity 
    t.boolean :laden, :default => false 
    end 
end 

但現在我想兩種特定類型的WingedThing,用自己鮮明的特點:

class CreateBats < ActiveRecord::Migration 
    create_table :bats do 
    t.integer :echolocation_volume 
    t.string :snout_type 
    end 
end 

class CreateBirds < ActiveRecord::Migration 
    create_table :birds do 
    t.string :beak_size 
    t.integer :number_of_feathers 
    end 
end 

這是一個很簡單的事做STI - 有BatBird繼承WingedThing

class Bat < WingedThing 

(獎金問題:這在數據庫中看起來如何?我每Bat和每個Bird生成WingedThing行嗎?這是我的理解,但請糾正我,如果我錯了。)

(從這可能錯誤的理解)但是,如果我想要,如果FlightlessBirdair_speed_velocity將是一個毫無意義的領域,它的負擔將是不道德的; FlightlessBird的所有實例都將在爲相應的WingedThing生成的DB行中包含空值條目ladenair_speed_velocity。這是比我需要的更多的數據,並不適合可擴展性,但我也不想完全刪除這些字段,因爲至少有兩個其他模型依賴於它們。

TL;博士我想什麼,能夠做的是有BirdBat能夠訪問兩者共同的特點,同時具有FlightlessBird同父表,但沒有產生一些特性數據庫中的空字段。

建模這樣的關係的最佳方式是什麼,以確保我可以獲得最薄的數據庫?

+0

爲什麼migrations從'ActiveRecord :: Base'而不是從'ActiveRecord :: Migration'繼承? – mdesantis 2014-08-31 15:19:43

+0

好問題。固定。 – Vardarac 2014-08-31 15:21:06

回答

2

首先,對於STI,您不會爲每個子類創建額外的表 - 您的蝙蝠/鳥表不會被使用。

其次空列通常非常輕量級。例如在postgres中,它們在每行上都有一個掩碼,表示哪些列爲空。位掩碼指示哪些列都存在,因此增加一個空列只會增加每行1位(撇開一些圍捕微妙之處)

你基本上有4種選擇:

  • 不使用STI(即每個模型一個表格,以及每個模型的所有屬性)。你仍然可以有一個共同的基類(它必須具有「自我」。abstract_class = TRUE)對於任何共享代碼

  • 使用STI,一些列未使用的一些子類

  • 使用STI,但有你的子類必須使用具有針對特定子類的額外列的表has_one關係

  • 連載非共享的屬性(即儘可能的DB而言它們都具有相同的屬性)

有有效的CA爲所有這些尋找答案 - 他們也有缺點。例如,如果您沿着可能找到的has_one路線走下去,取決於使用情況,您對額外表格有很多查詢。另一方面,如果你很少使用額外的屬性,那就太棒了。

雖然我真的不會出汗一些空列 - 你不可能注意到。