🐣

[Ruby on Rails] いいね機能の作成

2023/07/05に公開

テーブルの設計

いいね機能のテーブルは以下のようにします。

カラム名 データ型 カラムの説明
user_id integer 「いいね」したユーザーのid
book_id integer 「いいね」された投稿のid

モデルの作成

$ rail g model Favorite user_id:integer book_id:integer

これでモデルは完成です。

モデルの関連付けを行う

book.rb
has_many :favorites, dependent: :destroy
user.rb
has_msny :favorites, dependent: :destroy

bookモデルにfavorited_by?メソッドを作成する

book.rb
  def favorited_by?(user)
    favorites.exists?(user_id: user.id)
  end
  • exists?メソッドは存在するかどうかを true と false で返すメソッド
  • 今回は favoritesテーブルに 因数で渡された userの id が存在するかを返す

ルーティング

routes.rb
resources :books, only: [:index,:show,:edit,:create,:destroy,:update] do
   resource :favorites, only: [:create, :destroy] #ここから追加
  end
  • 親の resource の中に do と end を使用して、子の resource を書くことを
    ネストすると言う
  • ネストしたURLを作ることで、 params[:book_id] で Bookのidを取得できるようになる
  • いいね機能は 「一人のユーザーは一つの投稿に対して一回しかいいねが出来ない」 使用にため、 resource と単数系にすることで、 /:id が URLに含まれなくなる
  • resource は「それ自身の id がわからなくても、関連するモデルの id から特定できる」 といった場合に使用する

コントローラー

いいね機能のcontrollerを作成します。
いいね機能ではviewを表示する必要がないです

$ rails g controller favorites

いいね機能には create と destroyアクションが必要になるので定義します

favorites_controller.rb
  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.find(params[:book_id])

  • find メソッドで Bookモデルから いいねされた投稿の id をもらう

favorite = current_user.favorites.new(book_id: @book.id)

  • current_user.favorites は current_user に関連付けられた Favoriteモデルのいいねを指す
  • favorites.new は空のインスタンスを作成している
  • book_id: @book.id は作成されるいいねが指定される Bookのオブジェクトに関連付けをしている

favorite.save

  • いいねしたことを保存している

redirect_to request.referer

  • リクエストを行ったページに移動します。つまり同じページに戻るという意味です。

favorite = current_user.favorites.find_by(book_id: @book.id)

  • find_by は()の中の条件に合う最初のレコードを一つだけ返すメソッドです。
  • なので今回はログインしているユーザーはBookオブジェクトに関連付けられた favorite は存在するかを返します 見つからなかった場合 nil を返します

view

今回は部分テンプレートにいいね機能を書きます

_btn.html.erb
<% 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 %>

if book.favorited_by?(current_user)

  • ログインしているユーザーはいいねをしているか? という意味

link_to book_favorites_path(book), method: :delete do

  • link_to のオプションで、do から end までのオブジェクトにメソッドを指定して、リンクをつけます。

book.favorites.count

  • 何個いいねがあるかを数えます。

部分テンプレートなので、showページなどの書くときは以下のようにして使用します。

books_controller.rb
@book = Book.new
books/show.html.erb
<%= render "favorites/btn", book: @book %>

こちらの記事を参考にさせていただきました。

Discussion