Turbolinks5になってから「フォームでバリデーションエラーになったあとその画面をリロードしたときの挙動がTurbolinksを利用していないときと異なる」という問題がある。
2年半くらい前からIssueが立っている
POSTしたあとの画面をリロードしようとすると、通常は「フォームの内容を再送信しますか?」みたいな確認ダイアログが出る。しかしTurbolinks経由だと単にいまのURLをGETで取得しようとする*1。これは、Turbolinksがhistory apiを使って履歴を操作しているのが原因。history apiに履歴を足すときはGETとしてのURLしか足せないので、現状のTurbolinksの仕様では対応するのは無理ぽい(放置されている原因の一つはこれだと思う)
そもそもTurbolinks(というかBasecamp)的には、formは全部js経由にしてしまう方針なので上記の問題で困っていない、というのもありそう。Railsでform_withを使ったとき、デフォルトではremote: true
になる。
普通はajaxリクエストでリダイレクトはできないのだけど、turbolinks(turbolinks-rails)ではajaxでpostを受け付けたときのハックが書かれていて、redirect_toされたときはTurbolinks.visitを使うようにしてリダイレクトを実現している。なので正常系だけならremote: true
で問題ない。
バリデーションエラーになったときの対応が面倒で、これは独自に定義をしないといけない。DHHはSJR(Server generated Javascript Response)でやればいいと書いてる。ようするにcreate.js.erbみたいなやつ。
Provide form_with as a new alternative to form_for/form_tag · Issue #25197 · rails/rails
わかるんだけどバリデーションエラーを表示するためだけにそれをやるのってめんどいのですよね。画一的に処理できるgemをつくればいいのか。すでに誰か作っていそうだからそれでも良さそう。
追記
だれも作ってなさそうなので作った turbolinksとform_withを便利に使うためのgemを作った - おもしろwebサービス開発日記
そのあとに似たようなのが作られていたことに気づいた><
jorgemanrubia/turbolinks_render: Support for render
with Turbolinks in Rails controllers
*1:railsであればindexアクションのURLになるはず