【问题标题】:Threading on polymorphic comments多态注释的线程化
【发布时间】:2014-02-28 23:08:06
【问题描述】:

我已经设置了两个可以通过同一个 cmets 表进行注释的模型:

我的 cmets 架构:

  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

我的 cmets 控制器:

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

如何向已有的内容添加线程(回复 cmets)?

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

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

这是我在电影放映视图中看到的内容:

<%= 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 %>

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

<%= 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 %>

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4


    【解决方案1】:

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

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

    缺点很明显,不能接受:

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

    2. 您将很难依赖此结构。如果有一天你不想在线程中显示 cmets 但很明显,你......会踢石头。

    3. 如果你想在现有的评论系统上做,很难。

    其实一个简单的办法就可以解决问题:

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

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

    3. 显示时,显示所有带有reply_to null 的 cmets 列表。

    4. 然后对于每条评论,显示嵌套的 cmets 都有它的 id。并以递归方式进行。

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

    添加:递归渲染演示助手

    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
    

    【讨论】:

    • 谢谢比利,我们可以在聊天框中继续吗?
    • 凯蒂,如果回答对您有所帮助,我很高兴。对不起,我很快就走了,所以我不能聊天。如果您在编写想法时发现新问题,您可以发布新问题。
    • 我刚刚对问题进行了编辑,显示了我的表单和显示视图的外观。我如何实现您所描述的内容?
    • cmets 是否应该通过部分渲染?
    • Katie,是的,最好是局部渲染,渲染最好放在助手中,这样嵌套调用更容易。如果您是 Rails 新手,恐怕实施起来会有点困难。我添加了一个关于递归渲染概念的演示助手。慢慢来,你可以先从其他简单的功能开始。
    【解决方案2】:

    您可以将 parent_id 添加到作为自引用关系的 cmets 模型中。因此,父 cmets 的 parent_id 为 nil,所有子 cmets 的 parent_id 为该父评论。您实际上是在构建一棵树。

    Ancestory Gem 非常适合此操作或您自己的学习体验。

    【讨论】:

      猜你喜欢
      • 2018-04-08
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-10
      相关资源
      最近更新 更多