「Railsでいいね機能を実装する方法」でいいね機能の実装方法をご紹介しましたが、今回はそのいいね機能をAjax(非同期通信)実装する方法をご紹介いたします。
完成系は以下のような感じです。
環境
- Ruby 2.5.7
- Rails 5.2.4
前提
- この記事によって、いいね機能が実装済みであること
index.html.erbを編集
2つのlink_to(method: :delete と method: post)に remote: trueを追記します。
remote: trueを記載することで、Ajaxでの処理を実行することができます。
<div class="container">
<h1>記事一覧</h1>
<table class="table">
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td>
<% if post.liked_by?(current_user) %>
<% like = Like.find_by(user_id: current_user.id, post_id: post.id) %>
<%= link_to like_path(like), method: :delete, remote: true do %>
<span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: red;">
<span><%= post.likes.count %></span>
<% end %>
<% else %>
<%= link_to post_likes_path(post), method: :post, remote: true do %>
<span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: gray;">
<span><%= post.likes.count %></span>
<% end %>
<% end %>
</td>
</tr>
<% end %>
</table>
</div>
いいね機能の部分をテンプレート化する
index.html.erbと同じディレクトリに以下のファイルを作成し、いいね機能の部分をコピーし、貼り付けます。
<% if post.liked_by?(current_user) %>
<% like = Like.find_by(user_id: current_user.id, post_id: post.id) %>
<%= link_to like_path(like), method: :delete, remote: true do %>
<span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: red;">
<span><%= post.likes.count %></span>
<% end %>
<% else %>
<%= link_to post_likes_path(post), method: :post, remote: true do %>
<span class="glyphicon glyphicon-heart" aria-hidden="true" style="color: gray;">
<span><%= post.likes.count %></span>
<% end %>
<% end %>
部分テンプレート(_like.html.erb)を呼び出すため、いいね機能の部分があったところにrenderを記述します。
また、Ajaxの処理がされる部分を識別できるように id を記述します。
<div class="container">
<h1>記事一覧</h1>
<table class="table">
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td id="like-<%= post.id %>"> <!--idで識別できるようにする-->
<%= render "like", post: post %> <!--renderで部分テンプレートを呼び出す-->
</td>
</tr>
<% end %>
</table>
</div>
controllerの編集
各アクションの最後にredirect_backをしていましたが、redirect_backをすると再読み込みをしていまい、Ajaxが機能しません。
そのため、redirect_backを削除します。
def create
like = Like.new(user_id: current_user.id, post_id: params[:post_id])
@post = like.post
like.save
end
def destroy
like = Like.find(params[:id])
@post = like.post
like.destroy
end
jsファイルの作成
remote: trueによってjs形式のリクエストを送信しているため、実行するアクション名(createやdestroy)のjsファイルを最終的に探しに行きます。
そのため、app/views/配下にlikesフォルダを作成し、そのフォルダの中に create.js.erb と destory.js.erb を作成します。
$("#like-<%= @post.id %>").html("<%= j(render 'posts/like', post: @post) %>");
$("#like-<%= @post.id %>").html("<%= j(render 'posts/like', post: @post) %>");
idで識別し部分的にhtmlを書き換えます。
これで完成です。