在Rails中递归渲染树

von*_*otz 2 tree ruby-on-rails

我有一个act_as_tree模型,我想将其渲染到嵌套的HTML列表中:

<ol>
 <li> Content goes here
  <ol> recursion
    <li>goes</li>
  <ol> here
 </li>
</ol>
Run Code Online (Sandbox Code Playgroud)

使用递归函数通常应该很容易。但是,Rails强制代码和内容之间严格分开。

将树递归呈现为HTML-List并保留该分隔的“轨道方式”是什么?

谢谢!

Rub*_*cer 5

有两种方法可以做到这一点:

  • 部分方式
  • 递归函数方式

我不知道如何acts_as_tree工作,但是我将演示如何acts_as_nested_set工作,应该相似。

由于您询问递归方式,因此可以在视图范围内的函数中将内容与ruby分开:

<%
  def draw_tree(node)
    node.children.each do |child|
%>
      <li><%= child.name %>
<%
          if child.children.any?
%>
              <ol><% draw_tree(child) %></ol>
<%
          end
%>
      </li>
<%
    end; nil
  end
%>
Run Code Online (Sandbox Code Playgroud)

然后,为所有根节点渲染树(我重复一遍,这是针对的acts_as_nested_set,您将不得不对其进行调整-这不难做到):

<ol>
    <% Model.roots.each do |node| %>
        <li>
            <%= node.name %>
            <% if node.children.any? %>
                <ol><%= draw_tree(node) %></ol>
            <% end %>
        </li>
    <% end %>
</ol>
Run Code Online (Sandbox Code Playgroud)

以上所有代码应位于同一模板(.html.erb)中。当然,你可以partialize它。

使用partials的方法与上面类似,但是您无需为函数调用而是为节点渲染partial。但是我有一种印象(我还没有测试过想法),即递归函数的渲染速度应该比局部函数要快一些。

更新

对于acts_as_tree你只需要:

root=Model.where(parent_id:nil).first

所以:

<% root=Model.where(parent_id:nil).first %>
<ol>
    <% root.children.each do |node| %>
        <li>
            <%= node.name %>
            <% if node.children.any? %>
                <ol><%= draw_tree(node) %></ol>
            <% end %>
        </li>
    <% end %>
</ol>
Run Code Online (Sandbox Code Playgroud)