缩进深度优先搜索的每个子项(ruby on rails)?

Indent every child of a depth first search (ruby on rails)?

我是 rails 的新手,我想知道是否有一种简单(或不简单)的方法来缩进 DPS 的每个子项?

我有一个名为 "Comment" 的模型 has_many :comments 和 belongs_to :comment。在我看来,我已经实现了一个 DPS 来显示每条评论和对该评论的每条评论,以及对该评论的每条评论等。

我的代码如下所示:

<div class=feed>
 <% @comments.each do |comment| %>
  <% if comment.comment_id == nil # display all original comments %> 
   
   <!-- subject -->
   <div class="subject">
    <%= comment.subject %>:
   </div>

   <!-- create array of replies -->
   <% replies = Array.new %> 
   <% replies.push(comment) %>
   <% while replies.any? %>

    <% reply = replies[0] %>
    <% replies.delete_at(0) %>
    

    <!--- name -->
    <div class="comment">
     <%= User.find(reply.user_id).name %>
    <!-- comment -->
     <%= reply.body %>
     <% if user_signed_in? %>
      <%= link_to "reply", new_comment_comment_path(reply.id) %> 
     <% end %>
    </div>

    <% reply.comments.each do |further_replies| %>
     <% replies.push(further_replies) %>
    <% end %>
    <br>
   <% end %>
   <br>
  <% end %>
 <% end %>
</div>

我将每个评论推送到 "replies" 并逐一访问每个回复。

有没有什么好的方法可以缩进每个子评论?

谢谢!

您可以使用 act_as_tree 结构,在这种情况下您的模型将类似于 -

class Comment
   has_many :replies, class_name: 'Comment', foreign_key :comment_id
   belongs_to :user
end

你的 html 代码在那种情况下会非常简单,比如

<div class=feed>
  <% @comments.each do |comment| %>
    <div class="subject">
      <%= comment.subject %>:
    </div>
    <% comment.replies.each do |reply| %>   
      <div class="comment">
        <%= reply.user..name %>
        <%= reply.body %>
        <% if user_signed_in? %>
          <%= link_to "reply", new_comment_comment_path(reply.id) %>    
        <% end %>
      </div>
      <br>
     <% end %>
    <br>
    <% end %>
</div>

我想出了一个效果很好的不同方法。我在 "CommentsController" 中实现了递归深度优先搜索,它返回了 { comments => amount_to_indent } 的散列,其中评论按访问顺序排列。在视图文件中遍历哈希,在适当的地方使用注释和 amount_of_indent。

class CommentsController < ApplicationController

def index
  @comments = Comment.all

  # depth first search
  @visited = Hash.new
  @comments.each do |comment|
    if !comment.comment_id        # has not parent comment
      indent = 0
      comment_array = DFS(comment, @visited, indent)
    end
  end
end

def DFS(comment, visited, indent)
  visited[comment] = indent        # add elements in order in which they are   visited
  comment.comments.each do |reply|
      DFS(reply, visited, indent + 4)
  end
  visited
end

并且在视图文件中:

<div class="feed">
 <% @visited.each do |reply, indent| %>
  <!-- display subject of all parent comments -->
  <div class="subject">
   <% if !reply.comment_id? %> 
    <%= reply.subject  %>:
   <% end %>
  </div>

  <!--- name and content -->
  <div class="comment">
   <!-- preceed comment with indent -->
   <%= raw(('&nbsp') * indent) %>
   <%= User.find(reply.user_id).name + ":" + reply.body %>

   <% if user_signed_in? %>
    <%= link_to "reply", new_comment_comment_path(reply.id) %> 
    <!--%= link_to 'delete', response, method: :delete, data: { confirm: 'Are you sure?' } %-->
   <% end %>

  </div>
 <% end %>
</div>

如果有人遇到和我一样的问题!