如何将嵌套集中的所有记录渲染到真正的 html 树中 [英] How to render all records from a nested set into a real html tree
问题描述
我在我的 Rails 项目中使用了 awesome_nested_set
插件.我有两个看起来像这样的模型(简化):
I'm using the awesome_nested_set
plugin in my Rails project. I have two models that look like this (simplified):
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
中是允许的).
The tree in the database is constructed as expected. All the values of parent_id
, lft
and rgt
are correct. The tree has multiple root nodes (which is of course allowed in awesome_nested_set
).
现在,我想以正确排序的树状结构呈现给定客户的所有类别:例如嵌套的
标签.这不会太难,但我需要它是高效的(sql 查询越少越好).
Now, I want to render all categories of a given customer in a correctly sorted tree like structure: for example nested <ul>
tags. This wouldn't be too difficult but I need it to be efficient (the less sql queries the better).
更新: 发现无需进一步 SQL 查询即可计算树中任何给定节点的子节点数:number_of_children = (node.rgt - node.lft -1)/2
.这不能解决问题,但可能会有所帮助.
Update: Figured out that it is possible to calculate the number of children for any given Node in the tree without further SQL queries: number_of_children = (node.rgt - node.lft - 1)/2
. This doesn't solve the problem but it may prove to be helpful.
推荐答案
如果嵌套集具有更好的开箱即用功能就好了,不是吗.
It would be nice if nested sets had better features out of the box wouldn't it.
您发现的技巧是从平面集构建树:
The trick as you have discovered is to build the tree from a flat set:
- 从一组按 lft 排序的所有节点开始
- 第一个节点是根节点,将其添加为树的根节点移动到下一个节点
- 如果它是前一个节点的子节点(在 prev.lft 和 prev.rht 之间的 lft)向树添加一个子节点并向前移动一个节点
- 否则将树向上移动一级并重复测试
见下图:
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
这篇关于如何将嵌套集中的所有记录渲染到真正的 html 树中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!