2011-02-24 82 views
17

我有一些樹形結構的類別。我試圖通過爲每一個定義一個父項來將它們連接在一起。 (我不知道如何致電parent,因此它現在只是category,但它意味着父母)。創建一個具有樹形結構的模型

class Category < ActiveRecord::Base 

    has_one :category # the parent category 

end 

但是這種關係最終會以錯誤的方式結束。

吸氣功能是對孩子類別(正確),但category_id存儲在父:

parent = Category.create(:name => "parent") 
child = Category.create(:name => "child", :category => parent) 

parent.id # 1 
child.id # 2 

child.category_id # nil 
parent.category_id # 2 

child.category.name # "parent" (!!) 

父需要能夠有多個孩子,使這是行不通的。

回答

34

你在找什麼是自我連接。檢查軌道的這部分引導出:http://guides.rubyonrails.org/association_basics.html#self-joins

class Category < ActiveRecord::Base 
  has_many :children, class_name: "Category", foreign_key: "parent_id" 
  belongs_to :parent, class_name: "Category" 
end 

每個類別將belong_to父母,甚至是你的上級類別。您可以創建一個屬於您的最高級別類別的單個類別父級,然後您可以忽略應用程序中的這些信息。

+0

我同意阿德里亞諾,這是行不通的。當我做'obj.parent'之類的東西時,運行的查詢就像'select objs。* from objs where objs.parent_id = 3'看起來正確嗎?那麼obj.parent_id不是3,但它的ID是。儘管如此,「children」方法仍然有效。 – DJTripleThreat 2014-02-23 11:09:11

+0

我可以這樣做來改正你的答案: 'belongs_to:parent,:class_name =>「Category」,:foreign_key =>:id,:primary_key =>:parent_id' – DJTripleThreat 2014-02-23 11:16:31

+0

@DJTripleThreat你確定你沒有'你在'belongs_to'關聯上設置了'foreign_key'還是把外鍵('belongs_to')放在了父項上?這裏至關重要的一點是,你從子對象的關鍵字引用父對象,因此當你調用'child.parent'時,你將得到一個類似於'SELECT model。* FROM models WHERE id = child.parent_id LIMIT 1'。 – coreyward 2014-02-24 00:07:59

2

類別應該有很多類別,每個類別的外鍵應該是parent_id。所以,當你做parent.children它列出所有類別parent_id=parent.id

你讀過單表繼承嗎?

3

你可以使用acts_as_tree gem來實現這一點,找到下面的例子和鏈接。

https://github.com/amerine/acts_as_tree/tree/master

class Category < ActiveRecord::Base 
    include ActsAsTree 

    acts_as_tree order: "name" 
end 

root  = Category.create("name" => "root") 
child1 = root.children.create("name" => "child1") 
subchild1 = child1.children.create("name" => "subchild1") 

root.parent # => nil 
child1.parent # => root 
root.children # => [child1] 
root.children.first.children.first # => subchild1 
+1

另外[A​​ncestry](https://github.com/stefankroes/ancestry)寶石。 – 2016-01-05 01:09:40

+0

是的,它也很有趣。 – 2016-01-08 14:32:31

2

你應該看看祖先寶石:https://github.com/stefankroes/ancestry

它提供了你需要的所有功能,並能得到所有子孫,兄弟姐妹,父母,等用單SQL查詢通過使用物化路徑的變體,因此它會比上面的自連接和acts_as_tree回答具有更好的性能。