我试图在rails 5应用程序中使嵌套注释正常工作并遇到很多困难。
我正在建立一个问答网站,我有一个Acomment模型,其中有评论属于答案,然后有评论属于其他评论:
class Acomment < ApplicationRecord
belongs_to :answer
belongs_to :user
belongs_to :parent, class_name: "Acomment", optional: true
has_many :replies,
class_name: "Acomment", foreign_key: :parent_id, dependent: :destroy
end
我想显示所有评论,然后是所有回复评论,回复回复等等。但我无法弄清楚如何使嵌套正常工作。
在我看来,在每个循环中,我都在渲染_comment.html.erb
部分:
<% answer.acomments.each do |comment| %>
<%= render :partial=>"comment", :object=>comment %>
<% end %>
然后,在我的_comment.html.erb
部分内部,我显示评论,回复链接,然后呈现部分回复评论:
<div>
<%= comment.body %>
<%= link_to "Reply", new_acomment_path(:parent_id => comment, :answer_id => comment.answer) if comment.parent_id.blank? %>
<%= render partial: "reply", collection: comment.replies %>
</div>
这里是_reply.html.erb
部分:
<%= reply.body %>
<%= link_to "Reply", new_acomment_path(:parent_id => reply, :answer_id => reply.answer) %>
我遇到了两个问题:
1)当我渲染第一个部分时,它不仅渲染了注释,而且还同时呈现了回复(因为它们也是注释)。
2)当我渲染第二个部分(回复)时,它们不会嵌套在它们应该的注释中。一切都搞不定了。
编辑: 我希望看到这个:
Comment 1
Comment on Comment 1
Comment on Comment on Comment 1
Comment 2
但相反,这就是我所看到的:
Comment 1
Comment on Comment 1
Comment 2
Comment on Comment 1
Comment on Comment on Comment 1
Comment on Comment on Comment 1
非常感谢任何帮助。
答案 0 :(得分:3)
正如Taryn所写,你首先需要过滤没有parent_id的评论,这意味着他们是对答案的第一级评论。
视图/答案/ show.html.erb
<%= @answer.text %>
<h4>Comments</h4>
<% @answer.acomments.parents.each do |comment| %>
<%= render :partial=>"comment", locals: { comment: comment } %>
<% end %>
然后你需要一个递归方法:
视图/ acomments / _comment.html.erb
<div>
<%= comment.body %>
<%= link_to "Reply", new_acomment_path(:parent_id => comment, :answer_id => comment.answer) if comment.parent_id.blank? %>
<% comment.replies.each do |reply|
<%= render :partial => "comment", locals: { comment: reply } %>
<% end %>
</div>
您需要提供一些缩进,以便明确评论之间的层次结构。
答案 1 :(得分:1)
对于问题的第一部分,您可能需要一些范围来帮助您区分“父评论”(即不是答复的评论)和“儿童评论”(答复)。
类似的东西:
class Acomment < ApplicationRecord
belongs_to :answer
belongs_to :user
belongs_to :parent, class_name: "Acomment", optional: true
has_many :replies, class_name: "Acomment", foreign_key: :parent_id, dependent: :destroy
scope :is_parent, where(parent_id: nil)
scope :is_child, where("parent_id IS NOT NULL")
end
你可以使用下面的这些来渲染主循环中的父母......意图每个父母都会渲染自己的孩子。
<% answer.acomments.is_parent.each do |comment| %>
<%= render :partial=>"comment", :object=>comment %>
<% end %>
写下你的第二个问题 - 我需要更多信息 - 我会在上面的评论中提出。
后:
所以...我对正在发生的事情的猜测是:你只是得到了所有的评论(正如你所提到的)并且它们被显示在外部循环中(而不仅仅是在外部循环中显示的父项)并且它们按顺序排列,因为这是评论的数据库顺序。
由于partials中的默认命名约定,内部循环中实际上没有显示任何内容。
如果在部分中使用collection
- Rails会将每个项目提供给部分...然后在部分名称后面命名局部变量。在这种情况下,您尝试呈现名为“reply”的部分,但传入一组注释...因此partial将查找名为“reply”的变量。
我建议您重复使用已经使用的相同“评论”部分,而是以这种方式呈现:
<div>
<%= comment.body %>
<%= link_to "Reply", new_acomment_path(:parent_id => comment, :answer_id => comment.answer) if comment.parent_id.blank? %>
<%= render partial: "comment", collection: comment.replies %>
</div>
它将是递归的(就像Pablo的建议一样),因此通过缩进每一组子注释来呈现注释线程。
看看你与pablo的谈话...... parents
可能是一个范围的坏名字......听起来它可能会干扰一个名为同样的东西的ruby方法类层次结构...所以也许这是一个坏名字 - 因此我将重命名范围。