sql - 如何将嵌套集中的所有记录呈现为真正的 html 树

标签 sql ruby-on-rails ruby activerecord nested-sets

我正在使用 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 的所有值, lftrgt是正确的。树有多个根节点(这在 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/

相关文章:

sql - 此查询是否保证 'race free' PK 值?

ruby-on-rails - rails : how can I get unique values from column

ruby-on-rails - Rails AJAX 表单在验证失败后不重新填充字段

ruby-on-rails - 活跃商家 - 未初始化常量 ActiveSupport::XmlMini_REXML::StringIO

ruby - 如何使用ElasticSearch和Searchkick搜索日期范围?

c# - 如何将sql语句改为参数化查询?

sql - 使用 JPA 或数据库内部的级联删除/更新?

android - 为 sql db 创建多个表(a-z 表)

ruby-on-rails - 无法在 rails 2.3.5 中加载 rspec 生成器

ruby-on-rails - 有没有办法将当前的 url 拉到 Controller 中?