Railでの非同期通信(Ajax)を利用したいいね機能の実装

使用環境
Ruby2.6.8
Rails6.1.4

#完成イメージ
![スクリーンショット (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1193085/f7c1a964-2e29-07b8-d881-1f4b353a6571.png)


非同期通信を用いることで、上の画像の♡を押すと、ページの更新なしに「いいね」をつけたり、消したりすることができます。

##処理の流れを説明する前に・・・

####前提
railsでjQueryを読み込めるようにする必要があります。

https://qiita.com/tatsuhiko-nakayama/items/b2f0c77e794ca8c9bd74

また、非同期通信でいいね機能を実装するためには、javascriptでHTML構造を書き換える必要があります。なので、それぞれの投稿を部分テンプレートで切り出す必要があります。

![スクリーンショット (30)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1193085/e85480c9-31e6-8cd6-63b5-90198eb1a739.jpeg)

なので上の画像の水色で囲った部分は、javascriptで記述できるようにします。

以下に実際に実装したコードを例に説明していきます。


#処理の流れ
①「いいね」を送信(クリック)
②routeからコントローラに渡され、そこで「いいね」の保存、消去の処理
③「いいね」のデータをデータベースに格納
④ページの更新

##①「いいね」を送信(クリック)

まずは同期通信でいいね機能を実際に実装してみてください。

これが終わったらviewファイルを編集していきます。
いいね機能を実装していた箇所を以下のように変更してください。

```views/users/index.html.erb
<div id="likes_buttons_<%= @post.id %>">
    <%= render partial: 'users/index',locals: {post: @post} %>
</div>
```
このrederでいいね機能の部分を読み取ります。

```views/users/_index.html.erb
<% likes_count = Like.where(postId: post.id).count %>
<% if @current_user %>
	<% if Like.find_by(postId: post.id,userId: @current_user.id) %>
		<%= link_to "/likes/post/#{post.id}/delete",method: :post,remote: true do %>
			<span class="fa fa-heart like-btn-unlike"></span>
		<% end %>
	<% else %>
		<%= link_to "/likes/post/#{post.id}/create",method: :post, remote: true do %>
			<span class="fa fa-heart like-btn"></span>
		<% end %>
	<% end %>
	<%= likes_count %>
<% else %>
	<%= link_to("/necessary_login", {class: "favo-button"}) do %>
		<span class="fa fa-heart like-btn"></span>
	<% end %>
	<%= likes_count %>
<% end %>

```
上のファイル名の「_」はrenderで読み取る際には必須なので必ず忘れないように！！！

「_index.html.erb」のlink_toメソッドに注目してください。
「remote: true」と書かれているのが分かります。
(3つ目のlink_toはajaxしてませんが💦)

このremoteによってjavascript形式のリクエストを送信しているため、部分的な更新が可能となっています。

##②routeからコントローラに渡され、そこで「いいね」の保存、消去の処理　＆「いいね」のデータをデータベースに格納
ここは同期通信の時とおおきくは変わらないです。
routeの設定をしてあげましょう。

```route.rb
post "/likes/post/:id/create" => "likes#create"
post "/likes/post/:id/delete" => "likes#delete"
```

これでルーティングが通りました。
ではこのルーティングをlikesコントローラで受け取り、処理を実行しましょう。

```likes_controller.rb
class LikesController < ApplicationController

	def create
		@post = Post.find(params[:id])
		@like = Like.new(
			postId: params[:id],
			userId: @current_user.id
		)
		@like.save
	end

	def delete
		@post = Post.find(params[:id])
		@like = Like.find_by(
			postId: params[:id],
			userId: @current_user.id,
		)
		@like.destroy
	end
end
```
これで、「いいね」の登録、削除の処理が完了しました。

同期通信の際には、redirectでページの更新を行っていたと思いますが、今回はajaxで行うので、redirectの部分がある人は消去しちゃってください。

##ページの更新
コントローラのcreate、deleteメソッドが行われた際に実行するjavascriptの処理を記述しましょう。

「views」配下に「likes/create.js」と「likes/delete.js」を作成してください。
そいてそれぞれに以下のような記述をしましょう。

```views/likes/create.js
$("#likes_buttons_<%= @post.id %>").html("<%= j(render partial: 'users/index',locals: {post: @post}) %>");
```

```views/likes/delete.js
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'users/index',locals: {post: @post}) %>");
```
これで、先ほど作成した「_index.html.erb」のrebder部分（いいね機能の部分）のHTML要素を更新することができました。


参考
>https://qiita.com/naberina/items/c6b5c8d7756cb882fb20
>https://techtechmedia.com/favorite-function-rails/