如何将嵌套集中的所有记录渲染到真正的 html 树中 [英] How to render all records from a nested set into a real html tree

查看:24
本文介绍了如何将嵌套集中的所有记录渲染到真正的 html 树中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的 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_idlftrgt 的所有值都是正确的.树有多个根节点(当然在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆