#はじめに
すでにたくさんの記事が出ていますが、自分の備忘録的に書きたいと思います。
#非同期通信のメリット
個人的に「なぜその技術が使われているのか」を先に学習しておくことで、
目的がはっきりするため理解がはやい、、、気がします。
###1. ページを遷移することなく、ページの一部だけを更新できる。
いいねのたびにページが遷移されていては正直かなりわずらわしいかなと思います。
ですが非同期通信を用いることで、ページ遷移をすることなく、コメントができたり、いいねができたり、ユーザ編集ができたりするんです!
#実装!
###手順① サーバーにJS形式のリクエストを送る
まず、非同期通信でない場合、いいね実行時のターミナルは以下の挙動です。
画像の赤丸部分にリクエストの形式が出力されます。
この場合はHTML形式の通信になっているということですね!
こいつをJS形式にしたい、、、ということです!
<%= link_to post_favorites_path(post), method: :DELETE, remote: true do %>
このように、いいねボタンのリンクに remote: true を追記してあげることでJS形式のリクエストを送ることができます。
###手順② いいねボタンの部分テンプレートを作成する
非同期通信を実装するためには、変更部分を部分テンプレートにする必要があります。
具体的には、部分的に更新したい「いいね」の箱を用意して、
「いいね」しているか、していないかという状態で表示を切り替えるイメージです。
<% if post.favorited_by?(current_user) %>
<%= link_to post_favorites_path(post), method: :DELETE, remote: true do %>
<span class="btn btn-danger">いいね外す</span>
<% end %>
<% else %>
<%= link_to post_favorites_path(post), method: :POST, remote: true do %>
<span class="btn btn-primary">いいねする</span>
<% end %>
<% end %>
部分テンプレート views/posts/_favorites.html.erb を作成して、
いいねボタンの部分をこちらに移します。
そして元のindex.htmlで先程作成した部分テンプレートを呼び出します。
<div class="main_contents">
<% @posts.each do |post| %>
<div class="post_contents">
<h2><%= link_to post.title, post_path(post.id) %></h2>
<%= post.content %>
<!-- ↓追加(部分的に更新したい場所)↓ -->
<div id="favorite-<%= post.id %>">
<%= render 'posts/favorites', post: post %>
</div>
<!-- ↑ここまで↑ -->
</div>
<% end %>
</div>
###手順③ js.erbファイルを作成する
HTML形式リクエストの場合、viewファイルは views/コントローラ名/アクション名.html.erb
のファイルを呼び出します。
しかし、JS形式のリクエストの場合、 views/コントローラ名/アクション名.js.erb
のファイルを呼び出します。
今回は、favoritesコントローラーの、create,destroyアクションを使用していいね機能を実装してますので、
views/favorites/create.js.erb と views/favorites/destroy.js.erb
ファイルを作成します。
#id="favorite-<%= @post.id %>"この部分のHTMLだけ、renderで部分的に更新するという処理です
$("#favorite-<%= @post.id %>").html("<%= j(render 'posts/favorites', post: @post ) %>");
$("#favorite-<%= @post.id %>").html("<%= j(render 'posts/favorites', post: @post ) %>");
###手順④ コントローラーのリダイレクトを削除
def create
@post = Post.find(params[:post_id])
favorite = current_user.favorites.build(post_id: @post.id)
favorite.save
redirect_to root_path #←この行を削除
end
def destroy
@post = Post.find(params[:post_id])
favorite = current_user.favorites.find_by(post_id: @post.id)
favorite.destroy
redirect_to root_path #←この行を削除
end
#完成!
以上の手順でいいね機能の非同期化が実装できます!