繁体   English   中英

在rails上的ruby中嵌套注释和回复

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM