对嵌套注释使用 Rails 多态性

Posted

技术标签:

【中文标题】对嵌套注释使用 Rails 多态性【英文标题】:Using Rails polymorphism for nested comments 【发布时间】:2011-05-17 13:33:42 【问题描述】:

我需要在 Rails 3 应用程序中构建一个嵌套 cmets 系统,该系统允许在许多模型(文章、帖子等)上使用 cmets,并且我正在讨论按照this post 推出我自己的解决方案。有像 acts_as_commentable_with_threading 和 awesome_nested_set 这样的 gem,但它们对于我的需求来说有点臃肿。

    我需要能够将 cmets 添加到多个模型中 我需要能够将 cmets 添加到 cmets,无限深 我需要能够有效地检索帖子、文章等的所有后代 我需要能够在适当的嵌套中有效地呈现 cmets

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

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

【问题讨论】:

如果您必须使用 SQL 手动执行此操作,您知道该怎么做吗?如果是这样,我认为如果您可以使用内建命令(例如 belongs_to 和 has_many),这可能会帮助您形象化。这将反过来向您展示您的陷阱,或者是否有可能。 【参考方案1】:

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

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

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

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

您只需要使用两种方法来渲染整个 cmets 树:遍历 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_idawesome_nested_set 即可完成其余工作。我认为滚动您自己的解决方案不会比这更优雅。

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

【讨论】:

我同意。为此,我已切换回 awesome_nested_set。但是,这种方法不会针对每条评论(即使是那些没有孩子的评论)访问数据库吗?我看到了应该将整个树拉回根的后代方法,但我每次都得到一个空集。【参考方案2】:

是的,树结构是一个好主意 - 但是查询执行本身是最受关注的,我认为大多数树实现作为 gem 没有考虑到这一点,虽然嵌套集没问题 -我认为如果真的发生了非常糟糕的事情,那么它在写操作方面过于复杂了。

我会查看 Recursive CTEs - 虽然不是与数据库无关,但它为您提供了一个很好的数据结构,无需跟踪额外的属性即可使用。

【讨论】:

【参考方案3】:

我曾经通过在 cmets 表中添加以下字段来做类似的事情:

attached_to_controller(字符串)

attached_to_id (int)

然后在显示时,我将对 cme​​ts 索引进行 AJAX 调用,并根据这两个字段进行过滤。

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

【讨论】:

以上是关于对嵌套注释使用 Rails 多态性的主要内容,如果未能解决你的问题,请参考以下文章

ruby 中:Rails:嵌套路由,多态关联和控制器(https://medium.com/@loickartono/rails-nested-routes-polymorphic-as

iOS Core Data:为 Rails 多态关联设置关系的方法

markdown Rails中的多态性

Rails 5 - 使用多态关联 - 渲染视图

Rails 关联帮助 - 我是不是使用多态关联?

Rails:如何创建多态关系/友谊模型