2013-11-26 39 views
1

當一個頁面可以是另一個頁面的父頁時,我有頁面的層次結構。頁存儲在一個數據庫表結構如下:如何在Ruby on Rails中輸出層次結構列表

  • page.id
  • page.name
  • page.parent_id

現在我需要將它們輸出等級列表,像:

  • 頁A
    • 網頁B
    • 網頁C
      • 頁d
  • 頁面電郵

也沒有限制到多個層面。

在RoR中實現該目標的最佳方法是什麼?提前致謝。

回答

0

假設的代碼,而不是驗證。

class Page < ActiveRecord::Base 
    has_many :children, class_name: 'Page', foreign_key: 'parent_id' 
    belongs_to :parent, class_name: 'Page' 
end 

# Helper 
def tree_list(collection) 
    content_tag :ul do 
    collection.each do |item| 
     if item.children.blank? 
     content_tag :li do 
      item.name 
     end 
     else 
     tree_list(item) 
     end 
    end 
    end 
end 

# View 
tree_list(Page.all) 

的基本思想是tree_list方法將遞歸列表,直到沒有孩子的某一頁。

+0

謝謝,我試了一下,它的工作!幾個增強,但:1)嵌套content_tag是反直覺。詳情請參閱此鏈接:http://robots.thoughtbot。COM /嵌套內容標籤式護欄-3; 2)我改變了一下代碼:'def tree_list(collection) content_tag(:ul)do collection.each do | item | concat(content_tag(:li,item.name)) if!item.children.blank? concat(tree_list(item.children)) end end end end' 這是一個工作版本。 – temkin

+0

儘管這種方法有效,但我很可能堅持使用現有的寶石,以免重新發明輪子。無論如何感謝您的建議! – temkin

+0

這取決於用例,而不是發明車輪。如果只使用一種方法可以解決我的問題,我絕對不會去尋找寶石。這是簡單的基本原則。 –

0

正如其他用戶所建議的,您可以使用ancestry gem,但它需要對數據庫進行更改。如果你不能這樣做,你應該創建一個有向無環圖併爲每個節點設置深度。

class Page < ActiveRecord::Base 
    attr_accessor :depth 

    def children 
    @children ||= [] 
    end 
end 

# Loading required pages in single query, add predicate if needed 
pages = Page.includes(:parent).all 

# Setting up a hash table to find pages in constant time 
page_index = pages.reduce({}){|acc, page| acc[page.id] = page} 

# Setting up children 
pages.each do |page| 
    if page.parent_id 
    page_index[page.parent_id].children << page 
    end 
end 

# Basic depth-first search routine 
def dfs(page, visited, depth) 
    page.depth = depth 
    visited[page.id] = true 
    page.children.select{|p| visited[p] == nil}.each{|p| dfs(p, visited, depth + 1)} 
end 

# Performing depth-first search for each connected component 
visited = {} 
pages.each do |page| 
    if visited[page.id] == nil 
    dfs(page, visited, 0) 
    end 
end 

所以,現在每一頁都有一個深度屬性,只要你喜歡,你可以打印清單。