如何从一组嵌套的所有记录渲染成一个真正的HTML树 [英] How to render all records from a nested set into a real html tree
问题描述
我使用的 awesome_nested_set
插件我Rails项目。我有两个模型,像这样(简体):
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
).
现在,我想呈现的所有类别中特定客户的类似结构的正确排序树:比如嵌套的&LT; UL&GT;
标签。这将不会太困难,但我需要它是有效的(少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 - 节点.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
- 的第一个节点是根将其添加为树移动到下一个节点根
- 如果它是previous节点的子节点添加子树,向前迈进的一个节点 (介于prev.lft和prev.rht LFT)
- 否则移树一个级别,重复测试
- start with a set of all node sorted by lft
- the first node is a root add it as the root of the tree move to next node
- if it is a child of the previous node (lft between prev.lft and prev.rht) add a child to the tree and move forward one node
- otherwise move up the tree one level and repeat test
见下图:
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屋!