(Rails) javascript から Turbo Stream (fetch) を利用する方法

Published at: 2023/1/10


Rails 7 のデフォルト設定で turbo を利用する場合、 Turbo Stream は、データ変更系のフォーム送信(POST/PUT/DELETE)の戻り値というケースと、 turbo_stream_from で ActionCable 配信というケースが、資料等では説明される。

Turbo Stream は便利なので、これをいろいろ使い倒そうと調べていくと、たとえばこの記事にあるように、 GET なフォームや <a> タグによるページ遷移(のために Turbo が実行する javascript fetch)は、意図的に turbo 処理の対象から外されている、ということが分かる。 しかしこれは一方で、 DOM を更新する操作毎に別々の form を用意することが必要になったりしていて、ちょっと流石に融通が効かない感がある。

どうやったら融通を効かせられるかを考えていくと、これは基本的に javascript から任意の (rest) api を実行し、その結果を Turbo Stream 形式であるとして Turbo にどうにかして引き渡すことができれば、クリアされる技術的課題であると理解できる。 なのでそれを実行する方法はあるのかについて、調べてみた際の備忘録

javascript から turbo stream 反映を実行する方法

Is there a way to programmatically invoke a Turbo Stream? · Issue #34 · hotwired/turbo · GitHub

Ditto on the issue title. It would be nice to have a programmatic way to invoke a stream URL, same way we currently can trigger a visit with Turbo.visit(). Turbo.stream('/some/url/here').then(r => console.log('maybe even return a promise...

github.com

ちょうど、 Github の上記の issue が javascript から任意に Turbo Stream を実行する方法を質問している。 この記事によれば、 Turbo.renderStreamMessage(html) の関数が、引数 html を Turbo Stream であるとして処理し、その結果を DOM に反映してくれる Turbo の関数である、ということが見てとれる。

Rails への API コールまで含めた例として、以下が挙げられている。

fetch(href, {
     headers: {
       Accept: "text/vnd.turbo-stream.html",
     },
   })
     .then(r => r.text())
     .then(html => Turbo.renderStreamMessage(html))
//  optionally reflect the url    .then(_ => history.replaceState(history.state, "", href))

Tags: railsturbo