Hotwire を使って Rails 6.1 の scaffold を SPA にしてみた

2 min read読了の目安(約2200字

はじめに

DHH 兄貴が公開してくれた Hotwire 、Websocket でリアルタイム更新が反映できて便利だなと思いましたが、ちょっと触ってみたら、 get で画面遷移なしでHTMLを取得する時ってどうすればできるんだろう と疑問が出てきたので、 rails g scaffold の画面を SPA にしてみました。

Hotwire の基本については、公式のビデオと Hotwireでリアルタイムなチャットを作る を参考すればイメージできると思います。

結論

できたもの

https://github.com/blueplanet/hotwire-scaffold
  • 入力フォームを index に直接に表示することで、SPA にできました
    • bootstrap を導入して入力フォームを modal でやりたかったんですが、HTML が取得できたものの、 それを受けてから modal を表示する ところがうまくできなかったので、諦めました
  • SPA 対応のポイント

感想

  • hotwire-rails は、 turbo-railsstimulus-rails の組み合わせの設定をしてくれただけで、メインの仕事をしてくれているのは turbo-rails
  • turbo は5種類の動き append / prepend / replace / update / remove だけ定義されていて、それ以外の動きは stimulus で頑張ろう的な感じ
  • 更新系の処理をトリガーとして、view を更新する処理を broadcast すればよいですが、複数の処理が必要な場合、処理の順番をどう制限できるかは、まだ分かっていない
  • stimulus は、まだ良くわかってない

よかったところ

  • turbo_frame_tagdata: { turbo_frame: 'post_form' } と組み合わせるだけで、既存の scaffold で生成した view を SPA にすることができた
  • turbo_stream_frombroadcast* と組み合わせることで、修正系の結果をリアルタイムで反映できた

改善したいところ

  • webpacker があると、 turbo_frame_tag の中にある submit ボタンが Form submit のレスポンスが 200 になっているにもかかわらず disabled のままになっている事象がある
    • よって、できたものの rails project は、 --skip-javascript で初期化しました
    • 調べきれてなかったんですが、rails/ujs との整合性がよくない感じ
  • webpacker をなく、rails/ujs なくなり、form_with ... remote: true 系が使えなくなってしまうので、不便
  • ujs がなくても、You can still use the data-confirm and data-disable-with.ドキュメントに書かれています が、できたものでは、scaffold で生成した delete link は動きませんでした。

まとめ

  • turbo を使えば、js を書かなくて済むよ 的な感じがありますが、 turbo ならでは のやり方は、慣れる必要がある
  • ujswebpacker と併用できないため、既存プロジェクトへの導入はもうちょっと待つほうがよいかも

参考リンク