2009-02-17 30 views
52

我被困在一個奇怪的設計問題,單個表繼承和在哪裏在Rails中使用它

我在兩型曲線模型的工作,

  • 用戶配置文件(屬於用戶)
  • 其他人都在現場維持爲「機器人」(不屬於任何人)

這兩種類型的配置文件的典型OO行爲是相同的,但只是重要的屬性/屬性常見的(非常重要的5-6),其他屬性如「興趣等」(近10-15個屬性)不適用於機器人配置文件

此前編寫過的編碼器創建了單獨的模型/控制器機器人配置文件/用戶配置文件,這些配置文件在任何地方都會產生大量的冗餘,並且如預期的那樣難以維護,編寫測試等。我想幹這個,至少解決一些/所有這些冗餘問題。

有人建議單表繼承作爲解決

有人建議使用多態關聯代替。

什麼是更好的方法。我們什麼時候實際使用STI?

我自己的想法是,當模型的屬性相同且行爲不同時,STI最適用。

關於我該怎麼辦的想法?

回答

34

當屬性相同但行爲不同時,將STI描述爲非常有用的特徵是「大約正確」,但可能有一點限制。顧名思義,我喜歡在使用STI時使用清楚的OO風格繼承關係,而不是不同類型對象之間的數據庫風格關係。

如果在機器人和用戶之間有共同的代碼,我會說STI聽起來像是贏家。如果只有一些共同的屬性,它可能不太適用,但仍值得一試。

我是一個漂亮的實驗人員,所以我的建議是給它一個去。分支你的代碼並將模型重構爲STI關係。看看它是否確實乾涸了事情,或者只是爲其他問題交換一套頭痛。

有一件事我認爲你不會看到太多的好處是干擾你的控制器。根據我的經驗,STI模型通常不會轉化爲類似相關的控制器。但那是另一個可以嘗試的東西。有時候有勝利,有時候沒有勝利。

+0

我想要試驗性病,我想。但是如果我只有幾個共同的屬性,我可能會遇到什麼問題? – 2009-02-17 08:37:15

+1

處理控制器的另一種方法是對它們進行子類化,就像模型重構一樣,可以在它們之間共享通用方法。 – 2009-02-17 09:54:04

+0

@Andrew:IME,除了(相對少見的)裸骨架腳手架CRUD情況外,它幾乎不像模型的子類一樣工作。 – womble 2009-02-17 20:55:12

5

我可能會使用STI或根本沒有特殊功能。您可能可以將所有內容都調用爲配置文件,並且如果它的用戶爲零,您就會知道它是否爲「機器人」。您也可以在不使用STI的情況下存儲「類型」字段。

,有些事情會影響我的決定使用STI:

  • 是否有殭屍特定的邏輯
  • 多少殭屍有與用戶的配置文件(機器人的數量少意味着STI是OK - 大量的機器人,我可能會將它們存儲在其他地方)

避免性傳播感染的原因有時會妨礙您的行爲。例如,將一個對象從一種類型更改爲另一種類型(在這種情況下,將一個Bot添加到配置文件中)可能會相當麻煩。有時候一個簡單的「類型」字段更好。

值得注意的是,如果您使用STI,您可能需要共同的基類。所以你可能想要Profile,BotProfileUserProfile。名字取決於你。 :)

4

Rails STI的一個問題 - 大多數插件(等等)不完全支持它。你會發現自己修補了許多常見的東西。

29

我寫了一篇關於這個題目,包括一些小技巧與STI工作:

Single Table Inheritance in Rails

簡而言之:需要有對象之間的明確OO風格的繼承關係(如由womble雄辯地說),而不僅僅是一些共享數據。如果沒有自然而明顯的類層次結構,隨着應用程序的發展,STI設計可能難以維護。其次,你應該考慮在一張表中放置所有數據是否重要。通過多態關聯,數據庫查詢將變得更加複雜,並且可能會變慢。如果您計劃在網站上列出所有對象(例如,在一個表格中),那麼STI可能就是要走的路。

第三,確保你的子類沒有太多獨特的屬性。將所有數據放在一張表中,您不需要很多非全局列。這些不僅佔用空間(不是主要問題),而且會使數據結構混亂。如果你確實有「特殊」列,你應該在代碼中明確地解釋它們。

最後,如果您確實使用STI,我強烈建議您爲所有的孩子模型使用一個控制器。控制器的主要功能是提供對象的訪問權限,如果對象需要以非常不同的方式訪問,那麼STI可能不是正確的設計選擇。

看看我的文章(上面的鏈接)一些更有用的提示。