🍎
【Rails】コメント機能実装(同期)
- アプリケーション作成済
- 「Userモデル」「Bookモデル」「BookCommentモデル」を使用して実装
- コメント件数、コメント投稿内容、コメント投稿フォームを実装
- 完成イメージ ↓
1.BookCommentモデル、book_commentsテーブルを作成
ターミナル
$ rails g model BookComment comment:text user_id:integer book_id:integer
実行結果として下記が表示されればOK!
ターミナル
Running via Spring preloader in process 26537
invoke active_record
create db/migrate/20230725044406_create_book_comments.rb
create app/models/book_comment.rb
invoke test_unit
create test/models/book_comment_test.rb
create test/fixtures/book_comments.yml
ターミナル
$ rails db:migrate
- ここまでで「BookCommentモデル」「book_commentsテーブル」が生成された
- 「comment:text」=コメント用のカラム
- 「user_id:integer」「book_id:integer」=user_id,book_idを外部キーとして生成
2.アソシエーションを設定
- 1人のUserはコメントをたくさん持っている(複数の投稿にコメントすることができる)
- 1つのbookはたくさんのUserからのコメントを持っている
・・・つまり、UserとBookは「 多:多 」の関係性であるため、「 1:N 」の関係性を作れるように「中間テーブル」を作成する必要がある。
中間テーブルとして「book_commentsテーブル」を作成し、「user_id」と「book_id」を結びつける。
app/models/user.rb
class User < ApplicationRecord
:
has_many :books, dependent: :destroy
has_many :book_comments, dependent: :destroy ←これを追記!
- 「dependent: :destroy」=対象のUserが削除されたら、関連するBookCommentも削除される
app/models/book.rb
class Book < ApplicationRecord
:
belongs_to :user
has_many :book_comments, dependent: :destroy ←これを追記!
- 「dependent: :destroy」=対象のBookが削除されたら、関連するBookCommentも削除される
app/models/book_comments.rb
class BookComment < ApplicationRecord
belongs_to :user
belongs_to :book
end
3.ルーティング設定
app/config/routes.rb
Rails.application.routes.draw do
:
:
resources :books, only: [:new, :create, :index, :show, :edit, :update, :destroy] do
resources :book_comments, only: [:create, :destroy]
end
- Userがコメントしたのは、どの「本」なのか。がわかるように、booksコントローラーのルーティングにネストさせる
- createアクション(コメントを投稿)、destroyアクション(コメントを削除)を記述
$ rails routesの結果
ターミナル
book_book_comments POST /books/:book_id/book_comments(.:format) book_comments#create
book_book_comment DELETE /books/:book_id/book_comments/:id(.:format) book_comments#destroy
- ルーティングに「:book_id」が含まれている!
- params[:book_id]でBookのidが取得可能
4.コントローラー作成
ターミナル
$ rails g controller book_comments
ルーティングで設定したcreate、destroyアクションを記述
app/controllers/book_comments_controller.rb
class BookCommentsController < ApplicationController
def create
end
def destroy
end
end
5.アクションを実装
app/controllers/book_comments_controller.rb
class BookCommentsController < ApplicationController
def create
book = Book.find(params[:book_id]) #本のidを取得
comment = BookComment.new(book_comment_params) #ストロングパラメータのbook_comment_paramsを使ってnew(新規投稿)用の空のカラムを準備
comment.user_id = current_user.id #ログインしているユーザーのidを代入
comment.book_id = book.id #コメントを投稿する本のidを取得
comment.save #コメントを保存
redirect_to request.referer #アクション実行後に同ページに遷移(ページは変わらない)
end
def destroy
BookComment.find(params[:id]).destroy #本のidを取得
redirect_to request.referer
end
private
def book_comment_params
params.require(:book_comment).permit(:comment)
end
end
books/showページに実装するため、books_controller/showアクションに、コメントを投稿するための記述をする
app/controllers/books_controller.rb
:
def show
:
@book = Book.find(params[:id])
@book_comment = BookComment.new
end
:
6.ビューを作成
投稿詳細ページに「コメント数」「投稿されたコメント」「コメント投稿フォーム」を実装する
app/views/books/show.html.erb
:
:
#コメント数
<td>コメント数:<%= @book.book_comments.count %></td>
:
:
<table>
<tbody>
<% @book.book_comments.each do |book_comment| %>
<tr>
<td>
<%= link_to user_path(book_comment.user) do %>
<%= image_tag book_comment.user.get_profile_image(100, 100) %></br>
<%= book_comment.user.name %>
<% end %>
</td>
#投稿されたコメント
<td><%= book_comment.comment %></td>
<td>
#ログインしているユーザーであれば削除ボタンを表示
<% if book_comment.user == current_user %>
<%= link_to "削除する", book_book_comment_path(@book, book_comment), method: :delete %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
#コメント投稿フォーム
<div>
<%= form_with model: [@book, @book_comment] do |f| %>
<%= f.text_area :comment, rows: '5', placeholder: "コメントをここに", class: "w-100" %>
<%= f.submit "送信する" %>
<% end %>
</div>
ここまでで、コメントの投稿・削除・コメント表示・コメント件数の表示ができるようになりました!
7.バリデーション設定
コメントフォームが空欄の状態でも投稿できてしまうので、バリデーションを設定します!
app/models/book_comment.rb
class BookComment < ApplicationRecord
:
validates :comment, presence: true, length: { maximum: 200 }
- 「presence: true」=空欄ではない
- 「length: { maximum: 200 }」=最大200文字以内
ここまでで、コメント機能の実装が完了となります!
間違っているところ等ありましたらコメントいただけると幸いです🙇
こちらの記事を参考にさせていただきました!!
Discussion