【rails】いいね機能 非同期編
やっとできたので書いていきます。
↓前回まで
【rails】いいね機能実装 (追記あり) - 技術系ブログ
参考: 第14章 ユーザーをフォローする - Railsチュートリアル
[https://qiita.com/tambo/items/45211df065e0c037d032:title]
【Rails初心者】Ajaxの実装方法を理解する(非同期通信) - Qiita
導入手順
①jqueryを使えるようにします。
②remote: true 追加
③.js.erbファイル作成
④コントローラー側編集です。
そもそも非同期通信とは、
参考:非同期処理:コールバック/Promise/Async Function · JavaScript Primer #jsprimer
初心者目線でAjaxの説明 - Qiita
その前に同期通信は 同期処理ではコードを順番に処理していき、ひとつの処理が終わるまで次の処理は行いません。
同期処理では実行している処理はひとつだけとなるため、とても直感的な動作となります。
つまり、 同期処理ではひとつの処理が終わるまで、次の処理へ進むことができない。
非同期通信は、ひとつの非同期処理が終わるのを待たずに次の処理を評価します。
つまり、非同期処理では同時に実行している処理が複数あります。
一部分のみの更新とう言う感じですかね。
Ajaxとは
Asynchronous JavaScript + XML (AJAX) はそれ自体がある種の技術というわけではありませんが、
Jesse James Garrett によって 2005 年に作られた言葉で、既存の技術同士を組み合わせた新しいアプローチを意味します。
Ajax - Wikipedia
準備
jqueryを使えるようにします。
gem 'jquery-rails'
#app/asssets/javascripts/application.js -# バージョンがRails5.1以降の場合 //= require jquery //= require rails-ujs -# Rails5.1より前の場合 //= require jquery //= require jquery-ujs
view側
#app/views/likes/_like.html.slim
-if current_user.likes.find_by(post_id: @post.id)
#liked
= link_to post_like_path(@post, current_user.likes.find_by(post_id: @post.id)), method: :delete, remote: true do
p いいね済
- else
#likable
= link_to post_likes_path(@post,current_user.likes.build),method: :post, remote: true do
p いいね
(@post, current_user.likes.find_by(post_id: @post.id)),(@post,current_user.likes.build)
のように書いてアクション側にidを送ります。非同期導入前の段階では書かなくてもエラーが出ませんでしたが、
非同期通信をする際には必要なようです。
またremote: trueとそれぞれにidを追加しています
idを追加するとこで、jqueryのセレクタとして特定することができます。
remote: trueとは
参考:Rails で JavaScript を使用する - Railsガイド
フォームの送信がブラウザによる通常の送信メカニズムではなくAjaxによって送信されるようになります。
追加するだけでAjaxが使えるようになると考えてください。
そして、リクエストがhtml形式からjs形式になります。
つまり.jsファイルを探すようになります。
詳しく説明すると、link_to post_like_path(@post)ではhtml形式なら
controllerは「app/views/controller名/アクション名.リクエストの形式.erb」というファイルを探しに行きます。
しかし、今回のpostリクエストでいうと、html形式だとapp/views/likes/create.html.slimを探しますが,
js形式だとapp/views/likes/create.js.erbを読み込みます。
.js.erbファイルを作成
.js.erbファイルの作成にはファイル名を注意してください。
link_to先のアクション名に合わせてください。
app/views/controller名/アクション名.js.erbで作成します。
今回は、createとdestroy2つ作ります。
touch app/views/likes/create.js.erb
touch app/views/likes/destroy.js.erb
#app/views/likes/create.js.erb
$("#likable").html("<%= escape_javascript(render('likes/like')) %>");
#app/views/likes/destroy.js.erb
$("#liked").html("<%= escape_javascript(render('likes/like')) %>");
escape_javascriptメソッドは、JavaScriptファイル内にHTMLを挿入するときに実行結果をエスケープするために必要です。
コントローラー側
下記をcreate,destroyアクションにそれぞれ追加します。
respond_to do |format|
format.html { redirect_to @post }
format.js
end
respond_toメソッドとは、
上の (ブロック内の) コードのうち、いずれかの1行が実行されます。
#app/controllers/likes_controller.rb
class LikesController < ApplicationController
before_action :set_post, only: [:create, :destroy]
def create
@like = current_user.likes.create(like_params)
respond_to do |format|
format.html { redirect_to @post }
format.js
end
end
def destroy
@like = Like.find_by(like_params, user_id: current_user.id)
@like.destroy
respond_to do |format|
format.html { redirect_to @post }
format.js
end
end
private
def set_post
@post = Post.find(params[:post_id])
end
def like_params
params.permit(:post_id)
end
end
おしまい。