コメント機能の実装
コメント機能の実装
今回は、以前に作成したBookers2というアプリケーションにコメント機能を実装していく。
使用するアプリケーションについて参考URL 作成するアプリケーションについて - takifugu’s blog
コメント機能の作成
コメント機能を実装していく。
手順は下記の流れで作業していく。
コメントのモデルとテーブルの設計と作成。
関係性(アソシエーション)の記述
コメントのコントローラ作成
ルーティングの記述
コントローラにコメント作成のcreateアクション記述
ビューにコメント投稿欄の作成
コントローラにコメント削除のdestroyアクションの記述
ビューに削除ボタンの実装
コメントのモデルとテーブルの設計と作成
コメント保存用のテーブルには、「コメントの内容」「どの本の投稿にコメントするか。」「誰がコメントしたか。」を定義する必要がある。
このため、comment(コメントの内容)、book_id(どの本へのコメントか)、user_id(コメントした人)のカラムを持たせる必要がある。
カラム名 | データ型 | カラムの説明 |
---|---|---|
id | integer | コメントのID |
comment | text | コメントの内容 |
book_id | integer | コメントする本のID |
user_id | integer | コメントした人のID |
テーブルの設計が完了したので、book_commentモデルを作成する。
$ rails g model BookComment comment:text book_id:integer user_id:integer
データベースへマイグレーションする。
$ rails db:migrate
関係性(アソシエーション)の記述
Userモデル、Bookモデル、BookCommentモデルの関係性をER図で表すと下記のようになる。
UserモデルとBookCommetnモデル、BookモデルとBookCommentモデルの関係性をそれぞれ考えると、下記のようになる。
Userモデル:BookCommentモデル → 1:多
Bookモデル:BookCommentモデル → 1:多
上記を踏まえてモデルに記述をしていく。(アソシエーション部分を抜粋)
app/models/user.rb
has_many :books, dependent: :destroy has_many :book_comments, dependent: :destroy
app/models/book.rb
belongs_to :user has_many :book_comments, dependent: :destroy
app/models/book_comment.rb
belongs_to :user belongs_to :book
これでモデルの準備が完了しました。
コメントのコントローラ作成
book_commentコントローラを作成していきます。
$ rails g controller book_comments
ルーティングの記述
コメント機能は、コメント作成機能とコメント削除機能を実装するため、createアクションとdestroyアクションのルーティングを記述していく。
コメントは投稿した本に対して行われるため、book_commetnsはbooksに結びつき、下記のようにネストする記述を行います。
config/routes.rb(追加部分を抜粋)
resources :books, only: [:index, :show, :edit, :create, :destroy, :update] do resources :book_comments, only: [:create, :destroy] end
ルーティングの確認
$ rails routes
コメント投稿機能の実装
book_commentコントローラにコメント作成機能のアクションを記述する。
app/controllers/book_controller.rb
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 request.referer end private def book_comment_params params.require(:book_comment).permit(:comment) end
※redirect_to request.refererについて
Referer リクエストヘッダーには、現在リクエストされているページへのリンク先を持った直前のウェブページのアドレスが含まれています。
そのため、上記のような記述をすることで、直前のページにredirectすることができます。
bookコントローラのshowアクションに記述の追加
app/controllers/books_controller.rb
def show @book = Book.find(params[:id]) @book_comment = BookComment.new #追加 end
ビューにコメント投稿欄の作成
createアクションを記述したので、book_commentsフォルダに、コメント表示部分をindex.html.erb、コメント作成部分をform.html.erbとして部分テンプレートを作成する。
そして、books/show.html.erbにコメント作成機能、コメントの一覧表示を記述する。
app/views/book_comments/_form.html.erb
<%= form_with(model:[book, book_comment], local: true) do |f| %> <%= f.text_area :comment, rows:'5',placeholder: "コメントをここに", class: "w-100" %> <%= f.submit "送信" %> <% end %>
book_commentモデルはbookモデルにネストしているため、
book_commentモデルクラスのインスタンスにデータを保存するときは、form_withにbookとbook_commentの2つの引数を渡す必要がある。
rows: '5'でコメント投稿欄を5行に指定。
class: "w-100"で横幅100%というBootstrapを使用した記述。
app/views/book_comments/_form.html.erb
<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(50,50) %><br> <%= book_comment.user.name %> <% end %> </td> <td><%= book_comment.comment %></td> <td> </td> </tr> <% end %> </tbody> </table>
app/views/books/show
: </table> <%= render "book_comments/index", book: @book %> <%= render "book_comments/form", book: @book, book_comment: @book_comment %> :
上記でコメント投稿機能の作成が完了。
コメント削除機能の実装
次にコメント削除機能を実装していく。
destroyアクションの記述
book_commentsコントローラにdestroyアクションを記述していく。
app/controller/book_comments_controller.rb
: def destroy BookComment.find_by(id: params[:id], book_id: params[:book_id]).destroy redirect_to request_referer end :
BookComment.find_by(id: params[:id], book_id: params[:book_id]).destroy
URLから、IDとコメントをした本のIDを取得し、削除するコマンド。
削除ボタンの作成
book_commentsファイルの_index部分テンプレートのテーブルの要素に削除ボタンの追加。
自分が投稿したコメントのみに削除ボタンが表示されるようにする。
app/views/book_comments/_index.html.erb
: <td> <% if book_comment.user == current_user %> <%= link_to "Destroy", book_book_comment_path(book, book_comment), method: :delete, class: "btn btn-sm btn-danger", "data-confirm" => "本当に消しますか?" %> <% end %> </td> :
上記でコメント削除機能の作成が完了。
コメント件数の表示
ユーザーの詳細画面、本の一覧画面、本の詳細画面に登録されている本にコメント数を表示させていく。
本の詳細画面のテーブル要素に下記記述を追加。
app/views/books/show.html.erb
: <td> コメント数:<%= @book.book_comments.count %> </td> :
ユーザー詳細画面と本の一覧画面は、booksフォルダの_index部分テンプレートに記述を追加。
部分テンプレートのため、@はつけない。
app/views/books/_index.html.erb
: <td> コメント数:<%= book.book_comments.count %> </td> :
上記で、コメント件数の表示が完了。
以上。