多态注释线程化 [英] Threading on polymorphic comments
问题描述
我设置了两个可通过相同评论表进行评论的模型:
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:
很难把其他事情做好.例如,
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.
其实一个简单的解决方案就可以解决这个问题:
在评论模型中添加一个额外的字段
reply_to
,引用其他评论的id.
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屋!