動作環境
vscode、ruby3.3.0、rails7.1.3.4
実装したかったこと
x(旧twitter)のようなクローンアプリを作っていたのですが、投稿文に対するコメントに対して更にコメントする機能を実装してみました。
探せば山ほど参考になる記事は出てくると思ったのですが、今回は自分のテーブルや関係性の理解度を確認するために、敢えて自分で試行錯誤しながら一から作ってみました!💪
実装のゴール
コメントの子要素を取得できる。
コメントの3階層まで。4階層目のコメントは作成できない。(コメントのコメントのコメントまでは作成できる)
実装前のモデルの状態
user→post→comment
(既にpostへのコメント機能は作成済みです)
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
belongs_to :user
has_many :comments, dependent: :destroy
belongs_to :user
belongs_to :post, counter_cache: true
コメントの子コメントを取得できるようにする
コメントと子コメントを1対多の関係にする
コメントにparent_comment_idカラムを追加します。
class AddParentCommentsToComment < ActiveRecord::Migration[7.1]
def change
add_column :comments, :parent_comment_id, :integer
add_foreign_key :comments, :comments, column: :parent_comment_id
end
end
子コメントをchild_commentsという名前で定義します。
has_many :child_comments, class_name: 'Comment', foreign_key: 'parent_comment_id', inverse_of: :parent_comment, dependent: :destroy
コメントの親コメントを取得できるよう、親コメントをparent_commentという名前で定義します。
1階層目のコメントは親コメントがいないので、parent_commentとの紐付けは任意にします。
belongs_to :parent_comment, class_name: 'Comment', inverse_of: :child_comments, optional: true
3階層目以降のコメントは作成できないようにする
作成しようとするコメントのコメントのコメントのparent_comment_idカラムに値が入っていれば、つまり既に3階層になっていれば、保存できないようにするという処理を書きます。
どこかイけてない気がしなくもない…
FBをもとに改良したいと思います。
validate :layer_over_three
def layer_over_three
if self.parent_comment&.parent_comment&.parent_comment_id.present?
errors.add(:base, 'parent comment already has layers over three')
end
end
最後に
初めてコメントに対するコメント機能を作成しました。
社内のチャットシステムを見ながらいつも、どうやって実装しているんだろう?自分も実装してみたいと思っていたので、とりあえず実現できたのは良かったです。
画面の作成がまだ途中なので、画面の作成の完了次第、ビューファイルもアップしようと思います!