多态注释线程化 [英] Threading on polymorphic comments

查看:40
本文介绍了多态注释线程化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设置了两个可通过相同评论表进行评论的模型:

I've setup two models that are commentable through same comments table:

我的评论模式:

  create_table "comments", force: true do |t|
    t.text     "body"
    t.integer  "commentable_id"
    t.string   "commentable_type"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

我的评论模型:

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
  belongs_to :user
  acts_as_votable
end

我的电影模型

class Movie < ActiveRecord::Base
  belongs_to :user
  has_many :comments, as: :commentable
end

我的图书模型:

class Book < ActiveRecord::Base
  belongs_to :user
  has_many :comments, as: :commentable
end

我的评论控制器:

def index
  @commentable = find_commentable
  @comments = @commentable.comments
end

def create
  @commentable = find_commentable
  @comment = @commentable.comments.build(params[:comment])
  @comment.user = current_user
  if @comment.save
    flash[:notice] = "Successfully created comment."
    redirect_to @commentable
  else
    render :action => 'new'
  end
end

  def upvote_movie
  @movie = Movie.find(params[:movie_id])
  @comment = @movie.comments.find(params[:id])
  @comment.liked_by current_user

  respond_to do |format|
    format.html {redirect_to :back}
  end
end


  def upvote_book
  @book = Book.find(params[:book_id])
  @comment = @book.comments.find(params[:id])
  @comment.liked_by current_user

  respond_to do |format|
    format.html {redirect_to :back}
  end
end


private

def find_commentable
  params[:commentable_type].constantize.find(params[:commentable_id])
end
end

如何将线程(回复评论)添加到我已有的内容中?

How can I add threading(reply to comments) to what I already have?

这是一个讨论线程的博客:http://www.davychiu.com/blog/threaded-comments-in-ruby-on-rails.html

Here is a blog that talks about threading:http://www.davychiu.com/blog/threaded-comments-in-ruby-on-rails.html

我只是不确定如何将两者放在一起.

I'm just not sure how to put the two together.

以下是我的电影放映视图:

Here is what I have in my movie show view:

<%= render partial: "comments/form", locals: { commentable: @movie } %>


<% @comments.each do |comment| %>

<hr>
  <p>
   <strong><%= link_to comment.user.username, user_path(comment.user), :class => "user" %>
</strong> <a><%= "(#{time_ago_in_words(comment.created_at)} ago)" %></a>
  </p>

  <p>

    <%= simple_format(auto_link(comment.body, :html => { :target => '_blank' } )) %>
<% end %>

这是我的评论表单的样子:

Here is what my comment form looks like:

<%= form_for [commentable, Comment.new] do |f| %>
  <%= hidden_field_tag :commentable_type, commentable.class.to_s %>
  <%= hidden_field_tag :commentable_id, commentable.id %>
  <p>
    <%= f.text_area :body %>
  </p>
  <p><%= f.submit "Submit" %></p>
<% end %>

推荐答案

我浏览了您提到的文章,发现那里的解决方案非常有限.

I scanned the article you mentioned and found the solution there is quite limited.

文章中的基本思想是将评论本身设置为可评论.所以嵌套评论实际上不是帖子的评论,而是父评论的评论.

The basic idea in the article is to set a comment itself as commentable. So a nested comment is actually NOT a comment of the post, but of the parent comment.

缺点很明显且不可接受:

The drawbacks are apparent and unacceptable:

  1. 很难把其他事情做好.例如,posts.comments.size 不再正确.

您将非常依赖这种结构.如果有一天你不想在线程中显示评论,但说白了,你……会踢石头.

You'll have hard dependency on this structure. If in one day you don't want to display comments in thread but plainly, you...will kick a stone.

如果你想在当前的评论系统上做,很难.

If you want to do it on current comment system, it's hard.

其实一个简单的解决方案就可以解决这个问题:

  1. 在评论模型中添加一个额外的字段reply_to,引用其他评论的id.

  1. Add an extra field reply_to to comment model, referring to other comment's id.

添加评论时,如果回复了,请添加reply_to id.

When adding comment, add a reply_to id if it replied to one.

显示时,显示reply_to为空的所有评论列表.

When showing, show a list of all comments with reply_to null.

然后对于每个评论,显示嵌套的评论都有它的 id.并递归执行.

Then for each comment, show nested comments has its id. And do it recursively.

如果你想限制嵌套级别,你可以添加一个额外的 nested_level 字段,从前端获取.如果嵌套限制为 3,则不允许评论回复嵌套级别为 3 的评论.

If you want to limit the nested level, you can add an extra nested_level field, getting in from the front-end. If nest limit is 3, no comments is allowed to reply a comment with nest level of 3.

添加:demo helper 递归渲染

def render_replied_comments(comment)
  if comment.has_reply
    comments.replies.each do |reply|
      render partial: 'comment', locals: {comment: reply}
      render_replied_comment(reply)
    end
  end
end

# View
@post.top_level_comments.each do |comment|
  render partial: 'comment', locals: {comment: comment}
end

这篇关于多态注释线程化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆