Few days back, I was working on a project where I have to create nested comments on a articles and on showing the article I was needed to show all the nested comments in its hierarchy.So I used closure_tree gem to achieve that. So lets see how I implemented the nested comment functionality on article.
1) Add the following Gem to your Gemfile.
gem 'closure_tree'
2) Run the bundle to install the Gem
bundle
3) Now create the comments model which will have article_id (in case of root comment which will be posted directly on the article), parent_id (for storing the parent comment id), user_id, text (to store the content of the text)
rails g model Comment article:references parent_id:integer text:string
4) Now run the following migration for getting nested comments hierarchy
rails g migration create_comment_hierarchies
5) Inside this migration write the following code
class CreateCommentHierarchies < ActiveRecord::Migration
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
6) Inside Comment model write this line
acts_as_tree order: 'created_at DESC'
belongs_to :parent, class_name: "Comment"
has_many :childrens, class_name: "Comment", foreign_key: "parent_id"
7) Now during creation of the comment you need to create the comment like this:
def create
if params[:comment][:parent_id].present?
parent = Comment.where(params[:comment][:parent_id]).first
comment = parent.children.build(comment_params)
else
comment = Comment.new(comment_params)
if comment.save
render json: {success: true, message: "Comment Created Successfully"}
else
render json: {success: false, message: "Something went wrong"}
end
end
end
8) Now to get the hierarchy of a comment you just need to write like this:
Comment.hash_tree
and it will give you a result set like this:
{"k1l1" =>
{"k1l2" =>
{"k1l3" =>
{"k1l4" => {}
},
"k2l3" =>
{"k2l4" => {}}
},
"k3l3" => {}
}
}
You can also define the depth limit of the tree:
Comment.hash_tree(limit_depth: 2)
1 Comment(s)