Rails ブックマークの実装part2
part1からの続き
中間モデルを定義したので
ルーティング→コントローラ→viewと実装していきます。
ルーティングの設定
BoardモデルとBookmarkモデルが紐付いてるので、ルーティングをネストする必要がある。
commentsとbookmarksコントローラはboardsコントローラにネストしている。
Rails.application.routes.draw do root to: 'static_pages#top' get '/login', to: 'user_sessions#new' post '/login', to: 'user_sessions#create' delete '/logout', to: 'user_sessions#destroy' resources :users resources :boards do resources :comments, only: %i[create], shallow: true collection do get :bookmarks end end resources :bookmarks, only: %i[create destroy] end
collection
について
resourcesで定義されたアクション以外で別のアクションを追加する時に使用する。
今回は、boards_controllerにbookmarksアクションを使えるようにしている。
上記画像のbookmarks_boards GET /boards/bookmarks(.:format) boards#bookmarks
この部分ができる。
ブックマーク一覧ページを表示する際に使う。
ブックマーク一覧ページを表示するためのアクションを追加
def bookmarks @bookmark_boards = current_user.bookmark_boards.includes(:user).order(created_at: :desc) end
ブックマークを習得する際はN+1問題
に注意し、includes
メソッドを使用しユーザーを呼び出す。
bookmarks_controllerの実装
viewはいらないのでコントローラだけ作成。
class BookmarksController < ApplicationController def create board = Board.find(params[:board_id]) current_user.bookmark(board) redirect_back fallback_location: root_path, success: 'ブックマークしました' end def destroy board = current_user.bookmarks.find_by(params[:id]).board current_user.unbookmark(board) redirect_back fallback_location: root_path, success: 'ブックマークを外しました' end end
redirect_back(HTTP_REFERERが設定されていない場合のリダイレクト先 [, オプション])
redirect_back
で直前のページへリダイレクトさせる。
直前のページがない場合はfallback_location
でデフォルトのリダイレクト先を指定。
*この2つはセットで使う
board = current_user.bookmarks.find_by(params[:id]).board
について
current_userに紐付いたbookmarksの掲示板のレコードを取得している。
params[:id]
でルーティング/bookmarks/:id(.:format) bookmarks#destroy
のbookmarks/:idを取得し、
.board
で掲示板のレコードを取得している。
viewの実装
ブックマークボタンとブックマーク一覧ページの作成。
bookmark解除ボタン
<%= link_to bookmark_path(current_user.bookmarks.find_by(board_id: board.id)), id: "js-bookmark-button-for-board-#{board.id}", class: 'float-right', method: :delete do %> <%= icon 'fas', 'star' %> <% end %>
current_user
に紐づくbookmarksをboard_idが含むものを探し、取得する。
pathはrails routes参照。
bookmark DELETE /bookmarks/:id(.:format) bookmarks#destroy
サーバログからパラメータが拾えてるか確認。
bookmarkボタン
<%= link_to bookmarks_path(board_id: board.id), id: "js-bookmark-button-for-board-#{board.id}",class: 'float-right', method: :post, remote: true do %> <%= icon 'far', 'star' %> <% end %>
同じくpathとパラメータが拾えてるか確認。
bookmarks POST /bookmarks(.:format) bookmarks#create
ブックマークボタンを表示させる
掲示板一覧画面にブックマークボタン★☆を表示させる。
掲示板一覧画面では、ログイン中のユーザが作成した掲示板なら編集、削除アイコンを表示
別のユーザが作成した掲示板なら☆が表示されるようにする。
*イメージ図(meoでログイン中)
掲示板一覧画面へ表示させる
<% if current_user.own?(board) %> <%= render 'crud_menus', board: board %> <% else %> <%= render 'boards/bookmark_button', { board: board } %> <% end %>
user.rb
に定義しているown?
メソッドを使い、current_userが掲示板のuser_idと一致してるか判定している。
一致してれば編集、削除ボタンを表示、そうでなければ☆が表示される。
ブックマークしてるか判定するパーシャルを作成。
<% if current_user.bookmark?(board) %> <%= render 'unbookmark', board: board %> <% else %> <%= render 'bookmark', board: board %> <% end %>
user.rb
で前回作成した、ブックマークしているか判定するbookmark?
メソッドを使う。
もし、current_user
がブックマークしてたらunbookmark
(bookmark解除ボタン)をレンダーする。
そうでなければ、bookmark
(bookmarkボタン)をレンダーする。
これで、ブックマークすると「★」解除すると「☆」が実装される。
ブックマーク一覧ページの作成
レイアウトは掲示板一覧ページと同じ
boards_controllerのbookmarksアクションで定義した@bookmark_boardsをレンダーする。
〜 <% if @bookmark_boards.present? %> <%= render partial: "board", collection: @bookmark_boards %> <% else %> <p> ブックマーク中の掲示板がありません </p> <% end %> 〜
_header.html.erb
へリンクを追加したら完成。
<li class='nav-item'> <%= link_to 'ブックマーク一覧', '/boards/bookmarks', class: 'nav-link' %> </li>