我正在使用 awesome_nested_set
我的 Rails 项目中的插件。我有两个看起来像这样的模型(简化):
class Customer < ActiveRecord::Base
has_many :categories
end
class Category < ActiveRecord::Base
belongs_to :customer
# Columns in the categories table: lft, rgt and parent_id
acts_as_nested_set :scope => :customer_id
validates_presence_of :name
# Further validations...
end
数据库中的树按预期构建。 parent_id
的所有值, lft
和 rgt
是正确的。树有多个根节点(这在 awesome_nested_set
中当然是允许的)。
现在,我想在正确排序的树状结构中呈现给定客户的所有类别:例如嵌套 <ul>
标签。这不会太困难,但我需要它是高效的(sql 查询越少越好)。
更新:发现可以计算树中任何给定节点的子节点数,而无需进一步的 SQL 查询:number_of_children = (node.rgt - node.lft - 1)/2
.这不能解决问题,但可能会有所帮助。
最佳答案
如果嵌套集有更好的开箱即用功能就好了,不是吗。
您发现的技巧是从平面集构建树:
- 从一组按 lft 排序的所有节点开始
- 第一个节点是根将它作为树的根添加到下一个节点
- 如果它是前一个节点的子节点(lft 介于 prev.lft 和 prev.rht 之间)向树中添加一个子节点并向前移动一个节点
- 否则将树向上移动一层并重复测试
见下文:
def tree_from_set(set) #set must be in order
buf = START_TAG(set[0])
stack = []
stack.push set[0]
set[1..-1].each do |node|
if stack.last.lft < node.lft < stack.last.rgt
if node.leaf? #(node.rgt - node.lft == 1)
buf << NODE_TAG(node)
else
buf << START_TAG(node)
stack.push(node)
end
else#
buf << END_TAG
stack.pop
retry
end
end
buf <<END_TAG
end
def START_TAG(node) #for example
"<li><p>#{node.name}</p><ul>"
end
def NODE_TAG(node)
"<li><p>#{node.name}</p></li>"
end
def END_TAG
"</li></ul>"
end
关于sql - 如何将嵌套集中的所有记录呈现为真正的 html 树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1372366/