[Ruby on Rails] コメント機能の作成
テーブルの設計
カラム名 | データ型 | カラムの説明 |
---|---|---|
comment | text | コメント本文 |
user_id | integer | コメントをしたユーザーの id |
book_id | integer | コメントされた投稿の id |
モデルの作成
$ rails g model BookComment comment:text user:integer book_id:integer
モデルを作成した際にテーブルも作成したので、マイグレーションでデータベースに反映させる
$ rails db:migrate
モデルに関連付けを行う
has_many :book_comments, dependent: :destroy
has_many :book_comments, dependent: :destroy
belongs_to :user
belongs_to :book
コメント機能は user, book 共に 1対N の関係になるのでこのような書き方になります
コントローラーの作成
$ rails g controller book_comments
今回コメント機能は book/show 画面に設定するので、 アクションは create destroy
の2つになります。
def create
book = Book.find(params[:book_id])
comment = current_user.book_comments.new(book_comment_params)
comment.book_id = book.id
comment.save
redirect_to book_path(book.id)
end
def destroy
BookComment.find(params[:id]).destroy
redirect_to request.referer
end
private
def book_comment_params
params.require(:book_comment).permit(:comment)
end
解説
create
book = Book.find(params[:book_id])
- Bookモデルの id を取得
comment = current_user.book_comments.new(book_comment_params)
- ログインしているユーザーに紐付けて、空のインスタンスを作成し、params で指定したカラムを追加
- この部分は 以下の2つと同じ意味です
comment = PostComment.new(post_comment_params)
comment.user_id = current_user.id
comment.book_id = book.id
- コメントされた投稿の id と bookのオブジェクトの関連付けをしている
comment.save
- コメントを保存
redirect_to book_path(book.id)
- コメントをした後は book/show 画面に遷移するように設定
destroy
BookComment.find(params[:id]).destroy
- BookComment モデルから idをもらい、削除する
redirect_to request.referer
- request.referer はアクションを実行したページに遷移させるので、同じページに遷移される
book_comment_params
params.require(:book_comment).permit(:comment)
- params formから送られてくるデータが入っています
- require 送られてきたデータの中からモデル名を指定し、データを絞り込みます
- permit requireで絞り込んだデータの中から、保存するカラムを指定します
ルーティング
resources :book, only: [:new, :create, :index, :show, :destroy] do
resources :book_comments, only: [:create, :destroy] #ここを追加
end
- 親の resource の中に do と end を使用して、子の resource を書くことを
ネストする
と言う - 上記のような書き方をすることで、 params[book_id] で Bookの idを取得できるようになる
コメントを投稿するためのインスタンス変数を定義する
@book = Book.find(params[:id])
@book_comment = BookComment.new
Book モデルから id をもらいます
コメントを投稿するために新しいインスタンスを定義します
view 画面を作成する
<table>
<% if @book.book_comments.exists? %>
<% @book.book_comments.each do |book_comment| %>
<tr>
<td>
<%= book_comment.user.name %>
</td>
<td>
<%= book_comment.comment %>
</td>
<% if book_comment.user == current_user %>
<td>
<%= link_to "Destroy", book_book_comment_path(book_comment.book, book_comment), method: :delete %>
</td>
<% end %>
<% end %>
</tr>
<% end %>
</table>
<%= form_with model: [@book, @book_comment] do |f| %>
<%= f.text_area :comment %>
<%= f.submit "送信" %>
<% end %>
解説
<table>の中身
<% if @book.book_comments.exists? %>
- if はもし〇〇なら△△を実行という意味
- exists? は存在するかどうかを返します
<% @book.book_comments.each do |book_comment| %>
- 選択した投稿にあるコメントを1つ1つ取り出します
<%= book_comment.comment %>
- each で取り出したbook_comment のcomment を表示します
<% if book_comment.user == current_user %>
- もしコメントしたユーザーがログインしているユーザーなら表示します
<%= link_to "Destroy", book_book_comment_path(book_comment.book, book_comment), method: :delete %>
- link_to でリンクを作成
- book_book_comment_path はbook_commentsのdestroyアクションのpath
- delete を使用する際は、最後にmethod を指定する
form_with
` <%= form_with model: [@book, @book_comment] do |f| %>
- form_with ヘルパーを使用し、入力欄を作成します
- model オプションを使用し、 @book @book_comment の情報を追記します
- ブロック変数 f をモデルオブジェクトを作成します
<%= f.text_area :comment %>
- f.text_area は複数行のテキストフィールドを作成します
- :comment は @book_comment にある commentカラムと判断される
view 画面でコメント数を表示
コメント数:<%= @book.book_comments.count %>
これで表示させられます。
Discussion