後へ      Topへ      次へ

Turbo Stream: 画面の部分書き換え

「@step_options が期待する動作をしない件の改善」の2つ目です。

前章は、
Stimulus で、HTML の状態が変わったことをコントローラに伝えて受け取る処理でした。

本章は、受け取ったコントローラが、 画面書き換えに必要な HTML を生成する部分を説明します。

参考リポジトリ: https://github.com/Bonv-dev/book_mgmt/commit/a7e8840
\app\views\books\_select_place.html.erb
\app\controllers\books_controller.rb
\app\views\books\select_place.turbo_stream.erb

Turbo Stream

Turbo Stream は、
View (HTML) の一部だけを更新する仕組みの一つです。

コントローラのアクションでは、
一般に画面(HTML)のページ全体を更新します。

Rails8 のデフォルトでは
通常時でも Turbo Drive で HTML の <body> 部分のみを書き換えるのですが、
その場合は <body> 部分を「全体」と考えて頂ければ。

が、今回は Floor、Cabinet、Step 部分だけを書き換えたい。
その他のデータにまで気を配るのは面倒ですし、
全体を書き換えると画面更新に時間も掛かります。

Turbo Stream を使うことで、指定 ID 範囲のみを書き換えることが可能になります。

ターゲットの ID

通常時に使用する html.erb ファイル上、
Turbo Stream 発動時に書き換える範囲に ID を記載しておきます。

今回なら、
\app\views\books\_select_place.html.erb
<span id="select_place"> です。
ID の名前文字列は何でも良くて、一意に識別できればOKです。

_select_place.html.erb は、
book 編集画面のファイル \app\views\books\_form.html.erb の中で、
<%= render partial: "select_place" %>
として呼ばれます。
render partial は、指定ファイルの内容をこの場所に貼り付けます。  
ファイル名は、先頭にアンダーバー、末尾に (formats).erb を付けたもの。  
呼び出し側 _form.html.erb のフォーマットが html なので、
"select_place" なら ```_select_place.html.erb``` になります。  

 

respond_to - format.turbo_stream

前章の JavaScript が、
\app\controllers\books_controller.rb のアクション select_place を呼んだとします。
メソッドの中では普段と変わらない処理を行って、
画面書き換えに必要な選択肢のデータを揃えたりします。

最後に、

respond_to do |format|
  format.turbo_stream
end

部分ですが、 呼び出し時のパラメータで Accept: "text/vnd.turbo-stream.html" を指定しているので、
コントローラは、Turbo Stream での処理依頼だと認識しています。
結果、format.turbo_stream が選択されます。

普段は、\app\views\(コントローラ)\アクション名.html.erb が呼ばれるのですが、
今回は、\app\views\(コントローラ)\アクション名.turbo_stream.erb が呼ばれます。
今回なら \app\views\books\select_place.turbo_stream.erb です。

ちなみに、
respond_to ~ end 部分のコードが無くても、
Turbo Stream 時には .turbo_stream.erb が呼ばれます。
今回の select_place は Turbo Stream でしか使わないので、
つまり、
respond_to ~ end 部分は無くてもいいのですが、
明示しておくほうがコードを読む人間に優しいだろうと思います。

 

turbo_stream.erb

このファイルは特別で、
通常の画面の書き換え内容に加えて、
Turbo Stream で処理すべき指示も含んでいます。
単にファイルの内容を表示するわけではありません。

\app\views\books\select_place.turbo_stream.erb なら以下の通り。

<turbo-stream action="replace" target="select_place">
  <template>
    <%= render partial: "select_place", formats: :html %>
  </template>
</turbo-stream>

turbo-stream タグで、以下の設定を行います。

 

ちなみに、
select_place.turbo_stream.erb のフォーマットは Turbo Stream ですが、
呼び出す _select_place.html.erb は html なので、  
render に "formats: :html" を追加してフォーマットを明示します。

 

全体の流れ:再掲

前章と本章で、画面の部分書き換えの説明は終わりました。
最後に、全体の流れを再掲します。

  1. HTML (Stimulus)
    1. ユーザーがプルダウンメニューの選択肢を変更する
    2. Stimulus の action により、JavaScript が呼ばれる
  2. JavaScript (Stimulus)
    1. target のデータをチェックして、選択肢の状態を把握
    2. コントローラを呼ぶのに必要な url を生成
    3. fetch(url, { headers: { Accept: “text/vnd.turbo-stream.html” } })
      により、コントローラが呼ばれる
  3. コントローラ (Turbo Stream)
    1. 選択肢のデータを揃える
    2. respond_to - format.turbo_stream で
      (アクション名).turbo_stream.erb が読み込まれる
  4. turbo_stream.erb (Turbo Stream)
    1. turbo-stream タグの target ID に対して action を実施
    2. 結果が HTML の文字列になる。
    3. fetch した JavaScript に文字列を返す
  5. JavaScript (Turbo Stream)
    1. Turbo.renderStreamMessage(html) で画面を書き換える

後へ      Topへ      次へ