15
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-01-04

はじめに

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

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

結論

できたもの
https://github.com/blueplanet/hotwire-scaffold

  • 入力フォームを index に直接に表示することで、SPA にできました
    • bootstrap を導入して入力フォームを modal でやりたかったんですが、HTML が取得できたものの、 それを受けてから modal を表示する ところがうまくできなかったので、諦めました
    • turbo v7.0.0-beta.2 で異常系の status code の場合もレスポンスを描画するようになったので、stimulusturbo を使って、 成功したら modal をクローズ;エラーの場合そのまま を実現できた
# controller にエラー時の `render :new` に `status: :unprocessable_entity` 追加
def create
  @post = Post.new(post_params)

  respond_to do |format|
    if @post.save
      format.html { redirect_to @post, notice: 'Post was successfully created.' }
      format.json { render :show, status: :created, location: @post }
    else
      format.html { render :new, status: :unprocessable_entity }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

# form に turbo:submit-end イベントに `modal#close` メソッドを紐づく
<%= form_with(model: post, data: { controller: "modal", action: 'turbo:submit-end->modal#close' }) do |form| %>

# modal の close アクションに `event.detail.formSubmission.result.success` で結果を判定できる
close(event) {
  if (event.detail.formSubmission.result.success) {
    $('#post-modal').modal('hide')
  }
}

感想

  • 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 と併用できないため、既存プロジェクトへの導入はもうちょっと待つほうがよいかも

参考リンク

15
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?