12

如果您願意,可以給予一點幫助。爲遞歸關係編寫關聯

我想用我的'產品'類創建一個recusive relationsip。在哪裏我可以有一個產品作爲其他產品的父產品。我的問題是如何在我的模型中創建這種關係?

這是正確的嗎?

has_many :products 
belongs_to :product 

回答

38

邏輯沒有錯,你提出的解決方案。然而,你可能需要做這樣的事情:

belongs_to :parent, class_name: "Product", foreign_key: "parent_id" 
has_many :children, class_name: "Product", foreign_key: "parent_id" 

你基本上是在頂部和兒童產品分支存儲「樹」,一個產品的下方,可能很多層次深。

您示例中的策略被稱爲Adjacency List。很容易找到任何給定記錄的直接父母和直系後代。然而,獲得所有後代(包括後裔的後裔)可能會很困難,並且樹越深越難。

經常使用的替代方法是Nested Set,其中每條記錄都將有關該對象的信息存儲到它的「左」和「右」。這使您可以快速(或至少高效地在單個查詢中)構建樹,無論其大小如何。但是,它更復雜,插入記錄通常意味着必須重新計算並更新所有記錄到您插入記錄的右側。

第三個選項(可以說是一種中間立場)正在使用Path Enumeration,其中對象將其整個路徑存儲在樹中。所以,對於一個樹是這樣的:

A 
/\ 
B C 
    | 
    D 

A將有一個空白的路徑(無父),BC將有路徑AD將有路徑A/C。這種解決方案大多數插入操作相對便宜,查詢非常簡單。然而,它在樹中的相當複雜和移動的物體可能會變得昂貴。

還有其他選項,如Closure Tables

如果一個簡單的鄰接列表適用於您的需求,那麼去那個。這絕對是最簡單,最容易理解的。有些實現嵌套集合的寶石,也可能是其他一些樹形結構,所以如果你走這條路線,你不必自己動手。

+0

哇!真棒的答案,像你這樣的人使這樣的網站很棒。謝謝! –

+0

[This answer](http://stackoverflow.com/a/11162888/638425)在實現Closure Tables模式時可能非常方便。 – elhoyos

+0

很好的答案,謝謝你!對於使用一個模型的帖子進行評論很有幫助。 – Tomanow