投稿にいいね機能を実装する。
テーブルは、Users,Booksに加えFavoritesを追加する。
##実装の手順
①モデルの作成
②ルーティングを追加
③それぞれのモデルに関連付けを追加
④コントローラを作成
⑤Viewを作成する
###①モデルの作成
$rails g model Favorite user_id:integer book_id:integer
user_id:userとの紐づけ
book_id:book投稿との紐づけ
integer:データ型の整数
###②ルーティングを追加
resources :books do
resource :favorites , only: [:create , :destroy]
end
favoritesのshowページが不要で、idの受け渡しも必要ないので、resourceとなっています。
今回は、resources :booksにネストします。
resources :booksの中にresource :favorites , only: [:create , :destroy]を入れるという意味です。
ネストする理由は、ルートパスにあります。
#ネストしない場合
resources :books
resource :favorites , only: [:create , :destroy]
ネストしないとルートパスが、下図になります。実はこのままだと、どの投稿(book_id)にいいねを付けたか特定することができません。
ネストすることでルートパスが下図になります。投稿(book_id)を特定することができますね。
###③それぞれのモデルに関連付けを追加
has_many :favorites, dependent: :destroy
has_many :favorites, dependent: :destroy
def favorited_by?(user)
favorites.where(user_id: user.id).exists?
end
belongs_to :user
belongs_to :book
アソリエーション
※ user : favorite = 1 : 多
※ book : favorite = 1 : 多
1つのuserからみて、いいねは多数あるのでhas_many
1つのbook(投稿)からみて、いいねは多数あるのでhas_many
1つのいいねからみて、user・book(投稿)は1つしかないのでbelongs_to
has_manyの後にはdependent: :destroyを付けましょう。
**favorited_by?**メソッドを作成します。
このメソッドで、引数で渡されたユーザidがFavoritesテーブル内に存在(exists?)するかどうかを調べます。
###④コントローラを作成
rails g controller Favorites
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
#必要に応じてインスタンス変数を付けましょう。(book => @book)
current_userはログイン中のユーザーです。
request.refererは、元のviewに戻ってきます。いいねをクリック→いいねされたviewに戻ります。
なぜparamsの中が**:book_id**なのか?恐らくusr_idと混同するからと推測
###⑤Viewを作成する
#<% books.each do |book| %>
<% if book.favorited_by?(current_user) %>
<%= link_to book_favorites_path(book), method: :delete do %>♥<%= book.favorites.count %>
<% end %>
<% else %>
<%= link_to book_favorites_path(book), method: :post do %>♡<%= book.favorites.count %>
<% end %>
<% end %>
#<% end %>
#book/indexで投稿を全て表示しているので今回はインスタンス変数なし
<% if book.favorited_by?(current_user) %>
いいねがクリックされている状態と、されていない状態で表示を変えます。
<%= book.favorites.count %>
いいねされた数を表示しています。
以上で実装完了となります。