Turbo Drive とは？ Turbo Rails Tutorial をやってみた（3章）

本記事は、🔽「Turbo Rails Tutorial」の学習を進めていく際の個人メモです！

https://www.hotrails.dev/turbo-rails

🔽 前章の記事はこちら

https://qiita.com/yuppymam/items/ba18149d2a1afcc64556

# 3章 [Turbo Drive](https://www.hotrails.dev/turbo-rails/turbo-drive)

3章は「Turbo Drive とは何か」を理解するため、ちょっとした実験をしながら説明してくれる章となっています。

## Turbo Drive とは？
Rails7ではデフォルトで Turbo Drive が有効になっています。

```ruby: Gemfile
gem "turbo-rails"
```

```js: app/javascript/application.js
import "@hotwired/turbo-rails"
import "./controllers"
```
1章の時点で、すでに SPA チックになっていると気づきましたが、Rails7で`rails new`するだけで Turbo Drive になっているからなのですね！

Turbo Drive は、**すべてのリンクのクリックとフォーム送信を Ajax リクエストに変換**します。

## Turbo Drive が行うこと

1. `"click"`イベントや、フォームの`"submit"`イベントをインターセプト[^1]する
2. デフォルトの動作を上書きし、Ajax リクエストに変換する
3. リクエストの内容に応じて、HTMLページの`<body>`のみを置き換える

[^1]: 横取り、妨害のような意味だそうです。[インターセプト - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%82%BB%E3%83%97%E3%83%88)

ほとんどの場合`<head>`は変更されないため、高速になります。
（CSS や JavaScript ファイルのダウンロード要求は、Webサイトに最初にアクセスしたときに1度だけ実行されます。）

#### `status: :unprocessable_entity`
第１章では、空のフォーム送信時に何もエラーメッセージが表示されないことを確認しました。本来であれば空のフォーム送信時に422ステータスコードを返さなければならないのですが、Turbo では、4xx または 5xx ステータス コードを受け取った場合、例外的にリダイレクトをどう処理すればよいか分からないようです。

🔽 詳しくはこちらも参照

https://turbo.hotwired.dev/handbook/drive#redirecting-after-a-form-submission

## Turbo Drive を無効化してみる
Turbo Drive をまだサポートしていない gem を扱うときなど、Turbo Drive を無効にする必要がある場合があります。無効にするには、`data-turbo="false"`属性を追加する必要があります。

🔽 リンクで Turbo Drive を無効にする例
```erb
<%= link_to "見積もりを作成",
            new_quote_path,
            class: "btn btn--primary",
            data: { turbo: false } %>
```

Turbo Drive をオンオフして何が変わったかを、開発者ツールで確認できます。
Chromeであれば、検証の「ネットワーク」で、新たに要求されるリクエストの数が変わっているのを確認できます。

本チュートリアルでいうと「見積もりを作成」ボタンを押したとき以下の違いが出ます。

**Turbo Drive オフ**
- `Quotes#new`HTMLリクエスト
- favicon のロード
- CSSファイルのロード
- JavaScriptのロード

**Turbo Drive オン**
- `Quotes#new`Ajaxリクエスト
- favicon のロード



### アプリケーション全体で Turbo Drive を無効にする

以下のようにすることで、アプリケーション全体で Turbo Drive を無効にすることもできるようです。

```js: app/javascript/application.js
import { Turbo } from "@hotwired/turbo-rails"
Turbo.session.drive = false
```

## `data-turbo-track="reload"`とは？
先ほど、Turbo Drive のオン/オフで CSS と JavaScript のロードがあるかないかの違いが出ることが分かりました。しかし、CSS や JavaScript に変更があった場合、古い表示のままになってしまいます。

それを防いでくれるのが、`data-turbo-track="reload"`です。

`data-turbo-track="reload"`を持つDOM要素は、新しいリクエストごとに違いがないか比較して、違いがある場合はページ全体を再読み込みします。

デフォルトですでに設定されています。
```erb: app/views/layouts/application.html.erb
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
```

`data-turbo-track="reload"`の動作を確認するために、「見積もりを作成」ボタンを押したときの挙動を、CSSに変更を加えた場合とそのままの場合で比べました。CSSに変更がある場合はリロードするし、変更がなければ高速化してくれて、賢いですね！

## Turbo Drive のプログレスバー
Turbo Drive を利用していると、リンククリックやフォームの送信に対するブラウザ既定のプログレスバーは動作せず、代わりにCSSベースのプログレスバー(`turbo-progress-bar`クラスの`div`要素）を表示するようになっています。

🔽 参考

https://turbo.hotwired.dev/handbook/drive#displaying-progress

チュートリアルでは、`turbo-progress-bar`クラスに対してスタイルを追加し、オリジナルのプログレスバーに変身させました。（デフォルトではブルーでした）
![スクリーンショット 2023-02-11 17.57.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293962/3cbbfe3a-a81d-141e-5f4a-a28c074f2285.png)


ちなみに、プログレスバーの表示確認をするには、アクションを遅延させます。

```rb: app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action -> { sleep 3 }
end
```

これにて3章は終わり。Turbo Drive の少し深い部分の仕組みがわかって面白かったです。

🔽 次は4章をやっていきます。

https://www.hotrails.dev/turbo-rails/turbo-frames-and-turbo-streams