[英]Nested comments and replies in ruby on rails
I am working on my first project in ruby on rails and need to implement comments and replies functionality on it. 我正在研究我在ruby on rails上的第一个项目,需要在其上实现注释和回复功能。 I am facing of displaying replies under each comment as well as if any reply has child replies they need to display under it. 我面临着在每条评论下显示回复以及是否有任何回复都需要在其下显示的子回复。 structure will be some how as follow. 结构将如何如下。
first comment
Reply to first comment
reply to first comment first reply
reply to first comment
Second comment
Reply to second comment
and this nested structure continues. 这个嵌套结构继续。 I have only one table for these all comments with parent key to treat as reply. 我只有一个表用于这些所有注释与父键作为回复。 table structure is as follow 表结构如下
Id | Comment_body | parent_id | user_id | project_id
1 comment 2 2
2 comment/reply 1 2 2
3 comment/reply 2 2 2
this second comment is treated as reply for first comment and id 3 comment is treated as reply on first reply of first comment. 第二条评论被视为第一条评论的回复,而第3条评论被视为第一条评论第一次回复时的回复。 kindly help regarding to this nested structure that how i can manage it in a best way. 请帮助我了解如何以最佳方式管理它的嵌套结构。 Comment table also has association with project table and user table. 注释表还与项目表和用户表关联。 suggest the best way without gem as i already tried many of them but they are limited in depth level. 建议没有宝石的最佳方式,因为我已经尝试了很多但是它们的深度水平有限。
We've done this before . 我们以前做过这个 。 There's also a RailsCast about it.. 关于它还有一个RailsCast ..
The term you're looking for is recursion - self replicating. 你正在寻找的术语是递归 - 自我复制。
Use You can do this with acts_as_tree
:has_many / belongs_to
使用您可以使用acts_as_tree
:has_many / belongs_to
执行此操作
#app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :project
belongs_to :parent, class_name: "Comment" #-> requires "parent_id" column
has_many :replies, class_name: "Comment", foreign_key: :parent_id, dependent: :destroy
end
This will allow the following: 这将允许以下内容:
#app/views/projects/show.html.erb
<%= render @project.comments %>
#app/views/comments/_comment.html.erb
<%= comment.body %>
<%= render comment.replies if comment.replies.any? %>
The recursion occurs with render comment.replies
-- it will continue to loop through the replies
until there are no more. 使用render comment.replies
递归 - 它将继续遍历replies
直到不再有。 Although this will take some DB processing to do, it will display the comments with nesting. 虽然这需要进行一些DB处理,但它会显示带有嵌套的注释。
-- -
If you wanted to add a reply etc, you just have to populate the "parent" ID: 如果您想添加回复等,则只需填写“父”ID:
#config/routes.rb
resources :projects do
resources :comments #-> url.com/projects/:project_id/comments/:id
end
end
#app/views/comments/_comment.html.erb
<%= form_for [comment.project, comment.new] do |f| %>
<%= f.hidden_field :parent_id, comment.parent.id %>
<%= f.text_field :body %>
<%= f.submit %>
<% end %>
The above will submit to the comments#create
action: 以上将提交comments#create
action:
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
@project = Project.find params[:project_id]
@comment = @project.comments.new comment_params
end
private
def comment_params
params.require(:comment).permit(:parent_id, :body)
end
end
This is a rough outline of one approach to this (some elements may be missing, there may well be better ways and there may be glaring errors but hopefully this could be useful): 这是对此的一种方法的粗略概述(某些元素可能缺失,可能有更好的方法,可能存在明显的错误,但希望这可能有用):
=> Comment has_many :replies, dependent: :destroy
=>评论has_many :replies, dependent: :destroy
=> A comment will also need to accepts_nested_attributes_for :replies
=>评论还需要accepts_nested_attributes_for :replies
=> Reply belongs_to :comment
=>回复belongs_to :comment
=> Both will obviously need to belongs_to :user
=>两者显然都需要belongs_to :user
=> A Comment will need to belong_to
a post/article etc. =>评论需要belong_to
于帖子/文章等。
In Routes.rb you may want to nest replies within comments 在Routes.rb中,您可能希望在注释中嵌套回复
resources :comments do
resources :replies
end
How you integrate these with your post/article model is another question. 如何将这些与帖子/文章模型集成是另一个问题。
We'll need a CommentsController 我们需要一个CommentsController
class CommentsController < ApplicationController
def index
@users = User.all
@inquiries = Inquiry.all
end
def new
@user = User.find_by(id: params[:user])
@post = Post.find_by(id: params[:post])
@comment = @post.inquiries.new
@message = @comment.replies.build
end
def create
@user = User.find_by(id: params[:user_id])
@post = Post.find_by(id: params[:post_id])
@comment = Comment.create!(comment_params) #define these below
@comment.user << @user
redirect_to #somewhere
end
And a replies controller: 并回复控制器:
class RepliesController < ApplicationController
before_action do
@comment = Comment.find(params[:comment_id])
end
def index
@replies = @comment.replies
@reply = @comment.replies.new
end
def new
@reply = @comment.replies.new
end
def create
@reply = @comment.replies.new(reply_params)
#redirect somewhere
end
You can then build some views based on the above. 然后,您可以基于上述内容构建一些视图。 I should add that the closure_tree
gem does seem like a useful one to look at for this. 我应该补充说, closure_tree
gem看起来似乎是一个很有用的东西。 Having used the Mailboxer gem previously I would not recommend that though - as customising it is not always straightforwards. 之前我曾经使用过Mailboxer gem,但我不建议这样做 - 因为定制它并不总是直截了当。
I don't necessarily want to only suggest a gem, since you've said that you've already done your homework there, but I've used the mailboxer gem, ( https://github.com/mailboxer/mailboxer ), before for the same sort of use case to good effect. 我不一定只想建议一个宝石,因为你已经说过你已经完成了你的作业,但我已经使用了邮箱宝石,( https://github.com/mailboxer/mailboxer ),之前对于同类用例效果良好。 Admittedly, I had to hack it a little bit to handle some edge cases, but I think in your particular scenario, it would handle things just fine. 不可否认,我不得不破解它以处理一些边缘情况,但我认为在您的特定情况下,它会处理好的事情。 Perhaps more to the point, even if you have to make some changes, that's probably better than rolling your own from scratch. 也许更重要的是,即使你必须做出一些改变,这可能比从头开始自己滚动更好。
With that said, the data structure you've described is enough, in it's essentials to do what you're asking for. 话虽如此,你所描述的数据结构已经足够了,这是你要求做的事情的基本要素。 The final step would just be to set up the association on your Rails model: 最后一步只是在您的Rails模型上设置关联:
class Comment < ActiveRecord::Base
has_one :parent, class: 'Comment'
end
With that set up, you just need to make sure your views display your threading properly. 通过该设置,您只需确保您的视图正确显示您的线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.