Rails 非同期でいいね機能の実装
非同期リクエストって?
非同期リクエストとは、ページの再読み込みを行わずにサーバーとやりとりをすることで、Webページの動作を高速化する技術のこと。
Ajaxを利用することで実現され、非同期リクエストを行う際には、data: {"turbolinks" => false}を指定することで、Turbolinksが無効になるため、正しく動作することができる。
ajaxとは
Asynchronous Javascript and XMLの略
ウェブ開発において使用されるいくつかの技術の総称。
ページを更新することなくページの内容だけを入れ替えられる!
特徴
- ページの再読み込みをしない
- 処理の途中で他の操作もできる
例)SNSのいいねを押した後にいいねのボタンと数が変わる、マップのアプリでカーソルを移動すると、移動先の地図が連続で表示される
デメリット
- ページを更新しないということはURLが変わらないので、変化後の情報に直接アクセスできない
- 変更後に表示された文章は検索エンジンには引っかからないので、SEOの問題がある
- すべてのブラウザが対応しているわけではない
- セキュリティーやプライバーシの問題のすべてが解決しているわけではない
同期通信
- リクエストからレスポンスの1往復が終わらないと、次のリクエストは送信する事が出来ない
- クライアントは、リクエストしてからレスポンスが返るまで待機状態になる
- 同期通信は、送信と受信のタイミングを合わせた通信方式のこと
今回のエラーメモ
Rails 非同期でいいね機能を作る時、
jsが読み込まれているのにページをリロードしないといいねが変わらない問題が発生!
(jsは検証ツールでエラーを見れる)
caught ReferenceError: $ is not defined
このエラーはjQueryがロードされていないために発生する可能性があることを示している!
なので、
jQuery関連の
javascript/packs/application.jsをまず確認する。
import Rails from "@rails/ujs"
// import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import "jquery"
import "popper.js"
import "bootstrap"
import '@fortawesome/fontawesome-free/js/all';
import "../stylesheets/application"
Rails.start()
Turbolinks.start()
ActiveStorage.start()
//= require jquery
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
私がjqueryを入れる時に何かを間違っていて、
import "jquery"
と
同じ意味のrequire jqueryも入ってしまっていた!
(が、これはコメントアウトになっていたので関係なかった!)
importとrequireの違い_φ(・_・
2行目は、turbolinkが問題なんだ!と思い全体的に削除してしまっていたので復活させた。
turbolinkの記述の位置もミスっていて
部分テンプレートに下記が正しい記述で、
_favorite-btn.html
<% if book.favorited_by?(current_user) %>
<%= link_to book_favorites_path(book), method: :delete, remote: true , data: {"turbolinks" => false} do %>
<i class="fas fa-heart" aria-hidden="true" style="color: red;"></i>
<span style="color: red;"><%= book.favorites.count %></span>
<% end %>
<% else %>
<%= link_to book_favorites_path(book), method: :post, remote: true , data: {"turbolinks" => false} do %>
<i class="fas fa-heart" aria-hidden="true"></i>
<%= book.favorites.count %>
<% end %>
<% end %>
私はいいね機能を呼び出すrenderの部分に書いていた!
<!--いいね機能-->
<td id="favorite-btn_<%= @book.id %>">
<%= render 'favorites/favorite-btn', book: @book ,data: {"turbolinks" => false} %>
</td>
data: {"turbolinks" => false}この記述はrenderにもlink_toにも使えるの?
この記述は、RailsのUJSを使用して非同期リクエストを送信する際に使用されるlink_to、button_to、form_withなどのRailsフォームヘルパーとともに使用されることが一般的。
リンクやフォームが非同期リクエストを送信した場合にTurbolinksを無効にするためのオプションを提供する。
なので、renderにはdata: {"turbolinks" => false}を使用する必要はない。
renderにはdata: {"turbolinks" => false}を使用する必要はない理由は?
renderはページの再描画を行うための処理であり、デフォルトでTurbolinksが有効になっているため、data: {"turbolinks" => false}を指定する必要はない。
なるほど、、!
Turbolinksについての理解が重要だった!
👇
あと確認するところ
config/webpack/enviroment.jsファイル!
const webpack = require('webpack')
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: 'popper.js'
})
)
この記述から
下記の記述に変えた!
config/webpack/enviroment.js
const webpack = require('webpack')
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery',
})
)
1つ目の記述では、Popper.jsをインポートし、2つ目の記述では、jQueryのソースファイルをインポートしている、らしい。
1つ目の記述では
jQueryが定義されていないために発生していると考えられるエラーが発生してしまったため
2つ目の記述が正しいぽい。
JavaScriptを学ぶ前にいきなり非同期実装しようとして
Turbolinksに惑わされてしまったが何とか理解できてよかった🥲
🌱Turbolinksについてわかりやすい説明
明日Ajaxについてもっと詳しくまとめます!
Discussion