當一個頁面可以是另一個頁面的父頁時,我有頁面的層次結構。頁存儲在一個數據庫表結構如下:如何在Ruby on Rails中輸出層次結構列表
- page.id
- page.name
- page.parent_id
現在我需要將它們輸出等級列表,像:
- 頁A
-
- 網頁B
-
- 網頁C
-
-
- 頁d
-
-
-
- 等
-
- 頁面電郵
也沒有限制到多個層面。
在RoR中實現該目標的最佳方法是什麼?提前致謝。
當一個頁面可以是另一個頁面的父頁時,我有頁面的層次結構。頁存儲在一個數據庫表結構如下:如何在Ruby on Rails中輸出層次結構列表
現在我需要將它們輸出等級列表,像:
也沒有限制到多個層面。
在RoR中實現該目標的最佳方法是什麼?提前致謝。
假設的代碼,而不是驗證。
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
方法將遞歸列表,直到沒有孩子的某一頁。
謝謝,我試了一下,它的工作!幾個增強,但: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
儘管這種方法有效,但我很可能堅持使用現有的寶石,以免重新發明輪子。無論如何感謝您的建議! – temkin
這取決於用例,而不是發明車輪。如果只使用一種方法可以解決我的問題,我絕對不會去尋找寶石。這是簡單的基本原則。 –
正如其他用戶所建議的,您可以使用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
所以,現在每一頁都有一個深度屬性,只要你喜歡,你可以打印清單。
謝謝你讓我知道這個寶石。我是Ruby和Rails的新手,並不知道所有可能的選項。會試試看。 – temkin