[英]Nested comments and replies in ruby on rails
我正在研究我在ruby on rails上的第一个项目,需要在其上实现注释和回复功能。 我面临着在每条评论下显示回复以及是否有任何回复都需要在其下显示的子回复。 结构将如何如下。
first comment
Reply to first comment
reply to first comment first reply
reply to first comment
Second comment
Reply to second comment
这个嵌套结构继续。 我只有一个表用于这些所有注释与父键作为回复。 表结构如下
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
第二条评论被视为第一条评论的回复,而第3条评论被视为第一条评论第一次回复时的回复。 请帮助我了解如何以最佳方式管理它的嵌套结构。 注释表还与项目表和用户表关联。 建议没有宝石的最佳方式,因为我已经尝试了很多但是它们的深度水平有限。
我们以前做过这个 。 关于它还有一个RailsCast ..
你正在寻找的术语是递归 - 自我复制。
使用您可以使用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
这将允许以下内容:
#app/views/projects/show.html.erb
<%= render @project.comments %>
#app/views/comments/_comment.html.erb
<%= comment.body %>
<%= render comment.replies if comment.replies.any? %>
使用render comment.replies
递归 - 它将继续遍历replies
直到不再有。 虽然这需要进行一些DB处理,但它会显示带有嵌套的注释。
-
如果您想添加回复等,则只需填写“父”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 %>
以上将提交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
这是对此的一种方法的粗略概述(某些元素可能缺失,可能有更好的方法,可能存在明显的错误,但希望这可能有用):
=>评论has_many :replies, dependent: :destroy
=>评论还需要accepts_nested_attributes_for :replies
=>回复belongs_to :comment
=>两者显然都需要belongs_to :user
=>评论需要belong_to
于帖子/文章等。
在Routes.rb中,您可能希望在注释中嵌套回复
resources :comments do
resources :replies
end
如何将这些与帖子/文章模型集成是另一个问题。
我们需要一个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
并回复控制器:
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
然后,您可以基于上述内容构建一些视图。 我应该补充说, closure_tree
gem看起来似乎是一个很有用的东西。 之前我曾经使用过Mailboxer gem,但我不建议这样做 - 因为定制它并不总是直截了当。
我不一定只想建议一个宝石,因为你已经说过你已经完成了你的作业,但我已经使用了邮箱宝石,( https://github.com/mailboxer/mailboxer ),之前对于同类用例效果良好。 不可否认,我不得不破解它以处理一些边缘情况,但我认为在您的特定情况下,它会处理好的事情。 也许更重要的是,即使你必须做出一些改变,这可能比从头开始自己滚动更好。
话虽如此,你所描述的数据结构已经足够了,这是你要求做的事情的基本要素。 最后一步只是在您的Rails模型上设置关联:
class Comment < ActiveRecord::Base
has_one :parent, class: 'Comment'
end
通过该设置,您只需确保您的视图正确显示您的线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.