投稿に対するコメント機能実装の備忘録。
ゴール
- Userテーブル、Postテーブルに紐付く、Comentテーブル(中間テーブル)でコメントを管理。
- Comentテーブルは、コメント内容、コメントしたpost_id、コメント投稿者user_idカラムを設置。
- (前提) ユーザー機能は、devise を使用。
実装
コメントモデルとテーブル作成
- コメントモデルとテーブル(コメント内容、コメント投稿者)を作成
ターミナル
% rails g model Comment comment_text:text user:references post:references
% rails g controller Comments
% rails db:migrate
モデルにアソシエーション追加。
Commentモデル
belongs_to :post # Comment.post で、コメントされた投稿取得
belongs_to :user # Comment.user で、コメント投稿者取得
Userモデル
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy # User.comments で、ユーザーのコメント取得
validates :comment_text, presence: true, length: { maximum: 1000 } # 空をバリデーション、文字数制限とか。。
Postモデル
belongs_to :user
has_many :comments, dependent: :destroy # Post.comments で、その投稿のコメント取得
詳細ページにコメント欄設置
詳細ページ
-# コメント表示
= @comments.each do |c|
= c.user.name
- if c.user.id == @post.user.id # 記事投稿者
%p 投稿者
= simple_format(c.comment_text) # 改行ありで表示
= link_to '削除', post_comment_path(@post, c), data: {confirm: '本当に削除しますか?'}, method: :delete
-# コメント削除には、@post(親), @commentsのc に渡す必要がある
-# コメント投稿
= form_for [@post, @comment], local: true do |f| # comment は、postに紐づくので、配列で書く
= f.text_area :comment_test
= f.submit "投稿"
一覧表示ページに紐づくよう、ルーティングを設定。
routes.rb
resources :posts do # posts に紐づかせるため、ネストにする
resources :comments, only: [:create, :destroy]
end
コントローラーにアクション定義
コメント登録/削除アクション(create/destroy)。
ターミナル
% rails g controller comments
commentsコントローラー
before_action :set_post
before_action :authenticate_user! # ログイン中のみ許可
def create
@comment = @post.comments.create(comment_params)
if @comment.save
redirect_to blog_path(@post) notice: 'コメントしました'
else
flash.now[:alert] = 'コメントに失敗しました'
render post_path(@post)
end
end
def destroy
@comment = Comment.find(params[:id])
if @comment.destroy
redirect_to post_path(@post), notice: 'コメントを削除しました'
else
flash.now[:alert] = 'コメント削除に失敗しました'
render post_path(@post)
end
end
private
def set_post
@post = Post.find(params[:post_id])
end
def comment_params
params.required(:comment).permit(:comment_text).merge(user_id: current_user.id, post_id: params[:post_id])
end
投稿ページ(show)に、コメント一覧も表示するので、posts#showで、コメントデータ取得。
postsコントローラー
:
def show
@post = Post.find(params[:id])
@comment = Comment.new # フォーム用のインスタンス作成(コメント追加用)
@comments = @post.comments # コメント一覧表示用
end
: