2

我有一个简单的 Rails 应用程序,它显示一个页面,人们可以在其中发表评论并回复这些评论,等等。

评论的模型非常简单:

class Comment < ActiveRecord::Base
  attr_accessible :text, :parent_id
  attr_accessor :level

  has_many :replies, :class_name => 'Comment', :foreign_key => 'parent_id'
  belongs_to :parent, :class_name => 'Comment'

  scope :get_replies, where(parent_id: to_param})

end

并且,控制器将仅查看根级别的注释:

def index
  @root_comments = Comment.where('parent_id IS NULL')
end

最后,视图将获取根评论的回复评论并呈现所有内容:

<% @root_comments.each{ |c| c.level = 0} %>

<% while @root_comments.size > 0 %>
  <% comment = @root_comments[0] %>
  <% @root_comments.delete_at(0) %>
  <% replies = comment.get_replies %>
  <% replies.each{ |r| r.level = comment.level + 1} %>
  <% @root_comments = replies + @root_comments %>

  <div class="comment" style=<%= "margin-left:#{(comment.level * 50)}px;" %> >
    <%= comment.text %>
  </div>

<% end %>

到目前为止一切顺利......直到检查rails服务器输出和......

  Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE (parent_id IS NULL)
  Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE "comments"."parent_id" = 1
  Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE "comments"."parent_id" = 4
  ...
  Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE "comments"."parent_id" = 16
  Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE "comments"."parent_id" = 17

SQL查询无处不在...

我还没有找到任何关于内置 Rails 服务器优化来管理这种方法的信息。

1)任何人都知道这种优化是否存在?

2)如果它不存在,我该如何解决这个问题?


我试图在控制器中急切加载联系人,但服务器输出显示相同数量的查询。

@root_comments = Comment.includes(:replies).where('parent_id IS NULL')

谢谢!

4

3 回答 3

2

您可以做的一件事是将根评论与每个评论一起存储,因此您可以使用两个查询来查询所有评论:
* where('parent_id IS NULL') # 将这些评论的 id 提取到 root_ids
* where('root_id IN ?', root_ids)

缺点是您必须在代码中重建树。

于 2013-01-03T18:28:48.143 回答
1

你应该检查rails eager loading。尝试

 def index
  @root_comments = Comment.includes(:comment).where('parent_id IS NULL')
 end
于 2013-01-03T19:16:45.617 回答
0

我不确定它是否会帮助你的表现,但你可能想看看acts_as_tree gem:

https://github.com/amerine/acts_as_tree

至少,您可以避免重新发明轮子。

于 2013-01-03T01:32:43.620 回答