使用 Rails 多态性进行嵌套注释

发布于 2024-10-04 16:00:33 字数 704 浏览 0 评论 0 原文

我需要在 Rails 3 应用程序中构建一个嵌套评论系统,允许对许多模型(文章、帖子等)进行评论,并且正在讨论沿着 这篇文章。有一些可用的宝石,例如 acts_as_commentable_with_threadingawesome_nested_set,但它们对于我的需求来说感觉有些臃肿。

  1. 我需要能够向多个模型添加评论
  2. 我需要能够向评论添加评论,无限深
  3. 我需要能够有效地检索帖子、文章等的所有后代
  4. 我需要能够有效地呈现 我的

问题是,如果我推出自己的解决方案,我可能会面临哪些潜在的问题。我想避免走一条路只会到达死胡同。我最初的担忧与有效查询儿童有关。例如,获取文章后代评论(子项和子项的子项)的列表。

有人对此有意见吗?谢谢。

I need to build a nested comments system in a Rails 3 application that allows for comments on many models (articles, posts, etc) and am debating rolling my own solution along the lines of this post. There are gems available like acts_as_commentable_with_threading with awesome_nested_set, but they feel bloated for my needs.

  1. I need to be able to add comments to multiple models
  2. I need to be able to add comments to comments, infinitely deep
  3. I need to be able to efficiently retrieve all descendants for a post, article, etc
  4. I need to be able to efficiently present the comments in their appropriate nesting

My question is, were I to roll my own solution what potential hiccups I could face. I want to avoid going down one path only to reach a dead end. My initial concerns relate to efficiently querying for children. Say, for instance, getting a list of an articles descendant comments (children and children of children).

Anyone have input on this? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瞎闹 2024-10-11 16:00:33

您可以执行两种嵌套:树和嵌套集。

acts_as_tree 仅存储 parent_id,因此写入新条目非常快,但您必须递归遍历 id 编号链才能获取所有子项的列表。当您需要进行大量阅读时,这不是一个好的选择。

awesome_nested_set记录三位信息:parent_idlftrgt。计算左侧值和右侧值,以便它们包含该条目的所有子 ID。这对于读操作来说非常快,但对于写操作来说却很慢。

对于你的情况,我认为 awesome_nested_set 更合适。您可能认为这似乎有点过分了,但嵌套集合很快就会变得复杂。您需要使用嵌套集合模式来有效地查询子项。

您只需要使用两种方法来渲染整个评论树:迭代 Comment.roots 并为每个评论渲染 comment.children

class ModelController < ApplicationController
  def show
    @model = Model.find_by_id(params[:id])
    @comments = @model.comments.roots
  end
end

<ul id="comments">
<% @comments.each do |comment| %>
  <%= render :partial => 'comment', :object => comment %>
<% end %>
</ul>

<!-- _comment partial -->
<li class="comment">
  <!-- comment markup -->
  <% if comment.children.present? %>
  <ul>
    <%= render :partial => 'comment', :collection => comment.children %>
  </ul>
  <% end %>
</li>

要保存嵌套评论,只需填写 parent_id 即可,awesome_nested_set 将完成剩下的工作。我认为推出自己的解决方案不会比这更优雅。

更新awesome_nested_set 似乎有一段时间没有更新了。请查看 ancestry。做的事情基本上是一样的。

There are two kinds of nesting you can do: a tree and a nested set.

acts_as_tree stores only a parent_id and so it is really fast to write new entries, but you have to recursively walk the chain of id numbers to get a list of all the children. This is not a good choice when you need to do lots of reads.

awesome_nested_set records three bits of information: parent_id, lft and rgt. The left and right values are calculated so that they contain all the children ids for that entry. This is very fast for read operations but slower to write.

In your case I think awesome_nested_set is more appropriate. You might think it seems overkill, but nested sets get complicated in a hurry. You need to use the nested set pattern to efficiently query children.

You only need to use two methods to render the entire tree of comments: iterate over Comment.roots and for each comment, render comment.children.

class ModelController < ApplicationController
  def show
    @model = Model.find_by_id(params[:id])
    @comments = @model.comments.roots
  end
end

<ul id="comments">
<% @comments.each do |comment| %>
  <%= render :partial => 'comment', :object => comment %>
<% end %>
</ul>

<!-- _comment partial -->
<li class="comment">
  <!-- comment markup -->
  <% if comment.children.present? %>
  <ul>
    <%= render :partial => 'comment', :collection => comment.children %>
  </ul>
  <% end %>
</li>

To save a nested comment, simply fill in the parent_id and awesome_nested_set will do the rest. I don't think rolling your own solution will be any more elegant than this.

Update: Looks like the awesome_nested_set hasn't been updated in some time. Check out ancestry instead. Does basically the same things.

晨与橙与城 2024-10-11 16:00:33

是的,树结构是一个好主意 - 然而,最关心的是查询执行本身,我不认为大多数树实现作为 gem 考虑到这一点,而嵌套集是好的 - 我认为如果发生了非常糟糕的事情,就写入操作而言过于复杂。

我会查看 递归 CTE - 虽然与数据库无关,但它为您提供了一个很好的数据结构来使用,而无需跟踪额外的属性。

A tree structure, yes, is a good idea - however it is the query execution itself that is of the utmost concern and i don't think most tree implementations as a gem take this into account and whilst nested set is alright - i reckon if something really bad happened, its overcomplicated in terms of write operations.

I'd check out Recursive CTEs - whilst not database agnostic, it gives you a nice data structure to work with without having to have extra attributes to track.

心欲静而疯不止 2024-10-11 16:00:33

我曾经通过将以下字段添加到评论表中来执行类似的操作:

Attached_to_controller (string)

Attached_to_id (int)

然后,在显示时,我将根据这两个字段对评论索引和过滤器进行 AJAX 调用。

当然,在创建注释时,您需要为这些字段传递适当的值。

I used to do something like this by adding the following fields to the comments table:

attached_to_controller (string)

attached_to_id (int)

Then when showing I would make an AJAX call to the comments index and filter based on these two fields.

Of course, when creating comments you need to pass the appropriate values for these fields.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文