いいね機能
いいね機能の実装
今回も以前に作成したBookers2のアプリケーションにいいね機能を実装していく。
表示内容
投稿した本にいいねする機能を追加。
いいねは、一つの本に対して一人一回まで、もう一度押すといいねが消える。
本の一覧機能と本の詳細画面に表示する。
実装機能
コントローラ
favoritesコントローラの作成
createアクションの作成(いいねをする機能)
destroyアクションの作成(いいね削除機能)
モデル
favoriteモデルの作成 (用途:ユーザーと投稿のセットでいいねをしている状態とする)
ユーザーは一つの投稿に一つしかいいねできないこと
ビュー
投稿一覧画面にいいね数, いいね(する, 外す)ボタンを追加
投稿詳細画面にいいね数, いいね(する, 外す)ボタンを追加
いいねされていない投稿に対しては、いいね作成ボタンを表示させる
いいねされている投稿に対しては、いいね削除ボタンを表示させる
モデル
いいね機能のテーブルの設計
いいね機能のテーブル、favoritesテーブルについて設計していく。
いいねテーブルには、いいねのID、いいねした人のuser_id、いいねされた本のbook_idが必要である。
カラム名 | データ型 | カラムの説明 |
---|---|---|
id | integer | いいねのID |
user_id | integer | いいねした人のID |
book_id | integer | いいねされた本のID |
モデルの作成
Favoriteモデルを作成する。
$ rails g model Favorite user_id:integer book_id:integer
作成されたマイグレーションファイルをデータベース上に反映させる。
$ rails db:migrate
関係性(アソシエーション)の記述
Userモデル、Bookモデル、Favoriteモデルの関係性をER図で表すと下記のようになる。
UserモデルとFavoriteモデル、BookモデルとFavoriteモデルの関係性をそれぞれ考えると、下記のようになる。
Userモデル:Favoriteモデル → 1:多
Bookモデル:Favoriteモデル → 1:多
上記を踏まえてモデルに関係性の記述をしていく。
app/models/user.rb
: has_many :favorites, dependent: :destroy :
app/models/book.rb
: has_many :favorites, dependent: :destroy : def favorited_by?(user) favorites.where(user_id: user.id).exists? end :
favorited_by?メソッド
引数で渡されたuser_idがFavoritesテーブル内に存在(exists?)するかどうかを調べるメソッド
存在していればtrue、存在していなければfalseを返す。
app/models/favorite.rb
: belongs_to :user belongs_to :book :
これでモデルの記述が完了。
コントローラの作成
Favoritesコントローラを作成する。
$ rails g controller favorites
コントローラの作成が完了。
ルーティングの記述
いいね機能は、いいね作成機能といいね削除機能を実装するため、createアクションとdestroyアクションのルーティングを記述していく。
いいねは投稿した本に対して行われるため、favoritesはbooksに結びつき、下記のようにネストする記述を行います。
config/routes.rb
: resources :books, only: [:index, :create, :show, :edit, :update, :destroy] do resources :book_comments, only: [:create, :destroy] resource :favorites, only: [:create, :destroy] end :
いいね機能では、resourcesではなくresourceを使用している。単数形にすることで、/:idがURLに含まれなくなります。
これは、いいね機能が「一つの投稿に一つしかいいねできない」という条件のため、いいねのIDを取得しないでも、
ユーザーのIDといいねした本のIDを取得できれば削除機能を使用できるためである。
このように、resourceは「それ自身のidが分からなくても、関連する他のモデルのidから特定できる」といった場合に用いることが多いです。
ルーティングを確認すると下記のようになる。
$ rails routes
上記でルーティングの記述が完了。
いいね機能の作成
コントローラにcreateアクションとdestroyアクションを作成し、記述していく。
app/controllers/favorites_controller.rb
class FavoritesController < ApplicationController def create book = Book.find(params[:book_id]) favorite = current_user.favorites.new(book_id: book.id) favorite.save redirect_to request.referer end def destroy book = Book.find(params[:book_id]) favorite = current_user.favorites.find_by(book_id: book.id) favorite.destroy redirect_to request.referer end end
ビューにいいね欄の作成
いいね機能の部分テンプレートの作成
app/views/favorites/_favorite.html.erb
<% if book.favorited_by?(current_user) %> <%= link_to book_favorites_path(book), method: :delete, style: "color: red;" do %> <i class="fas fa-heart" aria-hidden="true"></i> <%= book.favorites.count %> <% end %> <% else %> <%= link_to book_favorites_path(book), method: :post do %> <i class="fas fa-heart" aria-hidden="true"></i> <%= book.favorites.count %> <% end %> <% end %>
上記の部分テンプレートをビューに追加していく。
app/views/books/_index.html.erb
: <td> <%= render 'favorites/favorite', book: book %> </td> :
app/views/books/show.html.erb
: <td> <%= render 'favorites/favorite', book: @book %> </td> :
いいね機能の実装が完了。
以上。