Make nested comment with gem closure_tree
Demo mà mình sẽ làm trong bài viết này là nested comment, mình sẽ tiếp tục làm demo dựa trên source code cũ bài viết trước của mình, sau khi hoàn thành nó sẽ như thế này nhé 1. Cài đặt gem "closure_tree" Thêm vào Gemfile rồi bundle install nhé 2. Chuẩn bị cho demo Những gì bạn cần ...
Demo mà mình sẽ làm trong bài viết này là nested comment, mình sẽ tiếp tục làm demo dựa trên source code cũ bài viết trước của mình, sau khi hoàn thành nó sẽ như thế này nhé
1. Cài đặt
gem "closure_tree"
Thêm vào Gemfile rồi bundle install nhé
2. Chuẩn bị cho demo
Những gì bạn cần là một demo comment ajax.
$ rails g model Comment content:text user:references post:references $ rake db:migrate
Khai báo trong routes.rb
resources :comments, only: [:create, :destroy]
Khai báo trong app/controllers/comments_controller.rb
class CommentsController < ApplicationController before_action :set_comment, only: [:destroy] def create @comment = Comment.create! comment_params respond_to do |format| format.html{redirect_to :back} format.js end end def destroy @comment.destroy redirect_to :back end private def comment_params params.require(:comment).permit :post_id, :user_id, :content end def set_comment @comment = Comment.find_by id: params[:id] end end
Khai báo trong app/controllers/posts_controller.rb
def show @comment = Comment.new @comments = @post.comments end
Khai báo app/views/posts/show.html.erb , app/views/comments/create.js.erb , app/views/comments/_comment.html.erb Bạn có thể xem thêm ở đây: https://github.com/ptnk1995/vote_demo/pull/2/files
3. Thêm nested comment
$ rails g migration add_parent_id_to_comments parent_id:integer $ rake db:migrate
parent_id sẽ lưu id của bình luận cha (nếu không có cha thì giá trị là null)
Chúng ta cũng sẽ tạo thêm 1 bảng mới để lưu hệ thống phân cấp bình luận.
$ rails g migration create_comment_hierarchies
Rồi khai báo trong migration này như sau:
class CreateCommentHierarchies < ActiveRecord::Migration[5.0] def change create_table :comment_hierarchies, :id => false do |t| t.integer :ancestor_id, :null => false # ID of the parent/grandparent/great-grandparent/... comments t.integer :descendant_id, :null => false # ID of the target comment t.integer :generations, :null => false # Number of generations between the ancestor and the descendant. Parent/child = 1, for example. end # For "all progeny of…" and leaf selects: add_index :comment_hierarchies, [:ancestor_id, :descendant_id, :generations], :unique => true, :name => "comment_anc_desc_udx" # For "all ancestors of…" selects, add_index :comment_hierarchies, [:descendant_id], :name => "comment_desc_idx" end end
rồi $ rake db:migrate nhé Để nó có thể nested, khai báo cần thiết là:
# models/comment.rb acts_as_tree order: "created_at ASC"
Và cần có những sự khai báo khác, bạn có thể xem thêm ở đây: https://github.com/ptnk1995/vote_demo/pull/3/files Trong pull này điều mình muốn note lại với bạn là:
- limit_depth: n : giới hạn cấp tối đa của nested là thứ n
<%= comments_tree_for @supports.comments_tree.hash_tree(limit_depth: 5), @post, @supports.comment %>
- Muốn hiển thị tất cả những bình luận lồng nhau, để giải quyết cho vấn đề hiển thị phức tạp thế này thì khai báo helper là điều cần thiết
module CommentsHelper def comments_tree_for comments, post, comment_new safe_join(comments.map do |comment, nested_comments| render(comment, post: post, comment_new: comment_new) + tree(nested_comments, post) end) end def tree nested_comments, post unless nested_comments.empty? content_tag :div, comments_tree_for(nested_comments, post, Comment.new), class: "replies" end end end
- Nếu bạn muốn khi xóa comment cha, thì những comment con cũng được xóa theo như comment facebook thì gem closure_tree có hỗ trợ cho bạn phương thức:
def destroy @comment.descendants.each do |comment_des| comment_des.destroy end @comment.destroy redirect_to :back end
descendants để lấy được các comment con của nó
4. Tham khảo
Muốn tìm hiển thêm về các phương thức, cũng như cách sử dụng của gem Closure_tree bạn có thể xem thêm ở đây: Doc gem Closure_tree
5. Source Code:
Demo Gem Closure_tree - By ptnk1995