4

以下は、html.erb で行われる反復ツリーで、ツリー構造の 2 レベルのみに達します。

      <ul>
    <li><%= root_template.id  %></li>
      <ul>
          <% for template in root_template.children  %>
              <li><%= template.id  %></li>
              <% if template.has_children? %>
                <ul>
                <% for template_child in template.children  %>
                    <li><%= template_child.id  %></li>
                <% end %>
                </ul>
              <% end %>
          <% end %>
      </ul>
  </ul>

結果: 反復

コードをヘルパー ファイルに移動し、再帰を適用してすべてのレベルに到達したいと考えました。

html.erb (つまり、テンプレートからルートを設定):

  <% html = '' %>
  <ul>
    <li><%= root_template.id  %></li>
    <ul>
        <%= recursive_tree root_template, html %>
    </ul>
  </ul>

次にヘルパーメソッド:

  def recursive_tree(root, html)
    html << ''
    if !root.has_children?
      html << "<li>#{root.id}</li>"
      return html.html_safe
    else
      for template_child in root.children
        html << "<ul>#{recursive_tree(template_child, html)}</ul>"
      end
    end
    return html.html_safe
  end

結果:間違った再帰結果

ヘルパーからテンプレートに適切なhtmlを送信する方法を理解するためにすでに1日を費やしましたが、デバッガーを使用しても、この再帰の問題と解決策を理解できませんでした。何か意見はありますか?

4

2 に答える 2

3

以下は、私が上記で抱えていた再帰的な問題に対する最終的な回答です。どちらも、次のような同様のテンプレート呼び出しを共有しています。

ソル 1 の場合:

  <% html = '' %>
  <ul>
    <%= recursive_tree root_template, html %>
  </ul>

ソル 2 の場合:

  <ul>
    <%= call_me_baby_two root_template %>
  </ul>

解決策1)上記の問題のある特定のコードをクリーニングなしで機能させる:

  • 説明 1) html コード全体を再帰呼び出しに渡していたので、これが最大の間違いでした。現在、空白文字列を渡して、再帰呼び出しがメインの html に戻った後に追加します。再帰のより深い呼び出しでは、そのようになります。
  • 説明 2)子の場合、ルートの ID を追加していませんでした。前の問題を解決した後にこれに気付きました。

    def recursive_tree(root, html)
    html << ''
    if !root.has_children?
      html << "<li>#{root.id}</li>"
      return html.html_safe
    else
      html << "<li>#{root.id}</li>" # Explanation 2
      for template_child in root.children 
        temp_html = '' # Explanation 1
        html << "<ul>#{recursive_tree(template_child, temp_html)}</ul>"
      end
    end
    return html.html_safe
    end
    

解決策 2)以下では、@davidrac の疑似コードを機能させるために余分な時間を費やしています。

  def recursive_tree_three(root)
    html=''
    if root
      html = "<li>#{root.id}</li>"
      if root.has_children?
        for template_child in root.children
          html << "<ul>"
          html << recursive_tree_three(template_child)
          html << "</ul>"
        end
      end
    end
    return html
  end

  def call_me_baby_two(root)
    recursive_tree_three(root).html_safe
  end
于 2013-01-06T23:54:46.990 に答える
1

ここで見つけられる 1 つの問題は、必要以上に html_safe を使用していることです。再帰メソッドの一部として html_safe があるため、より深いノードに対して何度も呼び出されます。

実装で間違っていると思われるもう 1 つの点は、<li>タグがタグを適切にラップしていないことです<ul>。そのため、複数の子を持つノードではおそらく間違った結果が得られます。

再帰メソッドを少し違った方法で構築できるかもしれません (ほとんどが疑似コードです):

def recursive_tree(root)
  res = ''
  if root
    res = "<li>#{root.id}"
    # if root has children
    #   add <ul>
    #   for each of the children res << recursive_tree(child)
    #   add </ul>
    # end
    res << "</li>"
  end
  res
end

ここで、ラッピング関数を追加して初期リストを作成し、html_safe を追加します。

wrapping_func(root)
  "<ul>#{recursive_tree(root)}</ul>".html_safe
end

ところで、期待している構造とhtml出力を質問に追加すると役立つ場合があります。

于 2013-01-06T07:55:31.137 に答える