我在Rails项目中使用了 awesome_nested_set 插件。我有两个看起来像这样的模型(简化):

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当然允许)。

现在,我想在结构正确排序的树中呈现给定客户的所有类别:例如嵌套的<ul>标签。这不会太困难,但是我需要它是有效的(sql查询越少越好)。

更新:知道无需进一步的SQL查询即可计算树中任何给定Node的子代数:number_of_children = (node.rgt - node.lft - 1)/2。这不能解决问题,但可能会有所帮助。

最佳答案

如果嵌套集具有更好的开箱即用功能,那就更好了。

您发现的技巧是从平面集中构建树:

  • 以按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
    

    关于sql - 如何将嵌套集中的所有记录呈现到实际的html树中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1372366/

    10-11 15:59