Rails 6.1.1にTurbo Driveをインストールして困ったこと

2021/01/25に公開

--skip-javascriptで開発していたRails 6.1.1のプロジェクトにStimulusを入れたくなり、ついでだからとhotwire-railsごと入れたらTurbo Driveで若干対応が必要だった話です。

大抵は公式のWebサイトリポジトリのREADMEに書いてあることなので、一通り読んでから導入すればハマらないと思います。

1. validation error時にエラーが表示されない

Redirecting After a Form Submission

通常railsでcreateアクションを書くとき、以下のようになっていることが多いと思います。

companies_controller.rb
  def create
    @company = Company.new(company_params)
    if @company.save
      redirect_to company_url(@company), notice: '登録しました'
    else
      render :new
    end
  end

以下のように status: :unprocessable_entity をつけてあげないと、エラーメッセージ付きのフォームが描画されません。

companies_controller.rb
  def create
    @company = Company.new(company_params)
    if @company.save
      redirect_to company_url(@company), notice: '登録しました'
    else
      render :new, status: :unprocessable_entity # <= status を追加
    end
  end

railsの本体の方でもscaffoldやドキュメントがこれに対応する形に変更されていますので、対応しておいて良いかと思います。
https://github.com/rails/rails/pull/41026

2. ログアウトしてもログイン状態のキャッシュが残ってしまう

以下のようにログアウト処理が書いてあったとします。
(rails-ujs gemを併用しています)

dashboard.html.haml
%h1 マイページ
- if logged_in?
  %p
    ようこそ #{current_user.name}.form_buttons
  = button_to session_path, class: 'form_button primary', method: :delete, data: { confirm: 'ログアウトしてよろしいですか' } do
    ログアウト

コントローラはこんな感じで普通にログアウト処理を行ってリダイレクト。

sessions_controller.rb
  def destroy
    logout
    redirect_to new_session_url
  end

これだとログアウトしたあとにブラウザバックすると、先ほどのログイン状態のキャッシュが表示されてしまいます。
Stimulus等を使ってJavaScriptでTurbo.clearCacheを呼んでも良いのですが、僕はめんどくさかったので以下のようにしてログアウトボタンに限ってTurboをオフにしました。

https://turbo.hotwire.dev/handbook/drive#disabling-turbo-drive-on-specific-links-or-forms

dashboard.index.haml
.form_buttons
  = button_to session_path, class: 'form_button primary', method: :delete, data: { confirm: 'ログアウトしてよろしいですか', turbo: false } do
    ログアウト

3. 違うlayoutを使うページに遷移したときに前のlayoutで読み込んでいたstylesheetのスタイルが引き継がれてしまう

Turbolinksの時と同じように data-turbo-track="reload" を使えば解決です。
Reloading When Assets Change

app/views/layout/admin.html.haml
    = javascript_include_tag 'application', data: { 'turbo-track' => 'reload' }
    = stylesheet_link_tag 'admin/application', media: 'all', data: { 'turbo-track' => 'reload' }

まだ作り始めて日が浅いアプリということもあって、このくらいの対応を行なったところで一通り導入完了した感じです。
また他に影響範囲を見つけたら追記します。

Discussion