🐎

【Ruby on Rails】複数のいいね機能の非同期処理の実装

2024/07/11に公開

はじめに

以前書きました【Ruby on Rails】【実装途中】複数のいいね機能の非同期処理に関しての実装が完了したので、今回はこちらの実装記録を投稿したいと思います。
苦戦した部分が多かったのですが、なんとか自力で実装できてよかったです。(スクールの講師の方に、実装の手助けとなる助言をいただき、やっと実装できました...)

単体のいいね機能ボタンの実装記事はよく拝見しますが、複数個のいいね機能の実装、およびその非同期処理に関しての記事は見当たらなかったので、参考になりましたら幸いです。

どのように実装したのか

下記が今回実装したものになります。

Image from Gyazo

前回の記事より修正した箇所

前回までは、create.turbo_stream.erbと、destroy.turbo_stream.erbの中で、条件分岐を行なっていなかったので、ボタンの状態(いいね/いいね解除)を切り替えられておらず、全てのボタンでいいね登録、いいね解除がされてしまう状態でした。

現在は、create.turbo_stream.erbと、destroy.turbo_stream.erbで、各いいねボタンが登録・解除を行ううように条件分岐させたビューを作成しました。
destroy.turbo_stream.erbでは、article.rbにunfavorited?のインスタンスメソッドを定義し、
emptyメソッドを使用して、空であればいいね登録のファイルと置き換えると実装しました。

前回の記事の中では、こちらの記事を参考に、all系のメソッドでCSSクエリセレクタを使うことで、複数のいいねボタンの非同期処理が可能かと認識していましたが、私の認識が誤っていたようです。
「複数の要素を対象に取れる」というのは、複数の非同期処理を同時に行える、という意味だったようです...
今回の複数個のいいねボタンの切り替えでは、replace_allメソッドではうまく実装できませんでした。
(1度いいね登録後、リロードしないと登録解除ができませんでした)

今回修正したコード

  • app/views/favorites/create.turbo_stream.erb
<% if @article.favorited?(current_user, :like_first) %>
<%= turbo_stream.replace "first-favorite", class: "like-button-1" do %>
  <%= render 'articles/first_unfavorite', article: @article %>
<% end %>
<% end %>

<% if @article.favorited?(current_user, :like_second) %>
<%= turbo_stream.replace "second-favorite", class: "like-button-2" do %>
  <%= render 'articles/second_unfavorite', article: @article %>
<% end %>
<% end %>

- 以下、3つ目以降のいいねボタンも同様のため、省略 -
  • app/views/favorites/destroy.turbo_stream.erb
<% if @article.unfavorited?(current_user, :like_first) %>
<%= turbo_stream.replace "first-unfavorite", class: "like-unbutton-1" do %>
  <%= render 'articles/first_favorite', article: @article %>
<% end %>
<% end %>

<% if @article.unfavorited?(current_user, :like_second) %>
<%= turbo_stream.replace "second-unfavorite", class: "like-unbutton-2" do %>
  <%= render 'articles/second_favorite', article: @article %>
<% end %>
<% end %>
- 以下、3つ目以降のいいねボタンも同様のため、省略 -
  • app/models/article.rb
def unfavorited?(user, type)
    favorites.where(user_id: user.id, favorite_type: type).empty?
end

今回実装で詰まった要因

今回実装に時間がかかってしまった原因です。半年後くらいに見返した時には、こんなことでつまづいていたのか〜となっていたいものです...

  • 条件分岐ではなく、idやclassでどのいいねボタンが登録・解除されるかを判断できるという認識があった
  • 条件分岐は、create.turbo_stream.erbやdestroy.turbo_stream.erbでは実装出来ないものだと思っていた(そのため、当初はコントローラーに条件分岐を記載していた)
  • 現在のユーザーがどのいいねボタンをクリックしたか?という条件分岐は、いいねボタンを読み込むパーシャルファイルで実装していたので、create.turbo_stream.erbやdestroy.turbo_stream.erbでは実装する必要がないと思い込んでいた

最後に

今回だいぶ苦戦しましたが、なんとか助言をいただき自力で実装できよかったです。
今後も1つのビューで複数箇所の非同期処理を行う場面が出てくるかと思ったので、自分の備忘録のためにも記事に記しました。
今回実装した内容より、より良い実装方法はあるかと思いますが、現状は上記が限界でした。
また数ヶ月後の自分が見返したときに、より良いコードが書けるよう今後も勉強を進めいきたいと思います。
ありがとうございました。

Discussion