Rails UJSをHotwire Turboにアップデート


原田です。今回は弊社サービスの定期的なアップデート作業の中から、最近行なった取り組みをひとつご紹介します。

プロジェクト管理ツールなら My Redmine!プロジェクトの課題やタスクの進捗をチームで共有。[PR] 1,000人使っても月額10,000円〜の定額制クラウド。国内実績多数。最大2ヶ月の無料お試しはこちら

きっかけ

弊社サービスMy Subversionで提供しているリポジトリ管理機能RepoMatはRuby on Railsを使用しています。アップデートは定期的に実施しているのですが、今回はRails UJSをHotwire Turboに置き換えようと思いました。

Rails UJSはRails6以前に標準で組み込まれており次の機能を提供していますが、Rails7以降は非推奨となりました。

Rails UJSは最新のRails8でも動作しますが公式のサポート(不具合の修正や新機能の追加)は終わっているので、早急にTurboにアップデートすべきと思い実施することにしました。

Turboにアップデート

今回のアップデートではTurbo DriveTurbo Streamsを使用します。主な特徴は以下のとおりです。

アップデート作業の一部をご紹介します。

Drive)redirect_toメソッドのHTTPステータスを303に変更

Rails6以前であればredirect_toメソッドのHTTPステータスはデフォルトの302 Foundで良かったのですが、Turboでリクエストを処理する時は303 See Otherを返す必要があります。

     if @user.destroy
       flash[:success] = t('flash.delete', model: t('activemodel.models.user'))
     else
       flash[:danger] = @user.errors.full_messages.first
     end
-    redirect_to users_path
+    redirect_to users_path, status: :see_other
   end

Drive)特定のリンクのキャッシュを無効化

Turboはキャッシュを使用するため、直前に表示していた入力画面(同じURIパス)に再度アクセスすると、前回と同じ内容(エラーメッセージ等)を表示することがあります。下記のようにlink_toメソッドにdata-turbo属性を設定し無効化することで、遷移後の画面表示でキャッシュは使用せずWebサーバーから最新のHTMLを取得し表示します。

     <% @groups.each do |group| %>
       <tr>
         <td>
-          <%= link_to group.name, show_group_path(group.name) %>
+          <%= link_to group.name, show_group_path(group.name), data: { turbo: false } %>
         </td>

Streams)Viewを使用して画面の部分描画

Ajaxのような非同期処理はTurbo Streamsに変更します。Streamsの利点の1つに非同期処理のレスポンスをStreams用のViewファイル(*.turbo_stream.erb)を介してブラウザに返します。これによりWebサーバー側で部分描画(既存Viewの再利用も可)やJavaScriptの実行も制御できます。

Viewファイル

+<%= turbo_stream.update('alert_messages', partial: 'layouts/alert_messages') %>
+<% member_ids&.each do |user_id| -%>
+  <%= turbo_stream.append('members', partial: 'groups/member', locals: { group: group, member: User.find(user_id) }) %>
+<% end -%>
+<%= turbo_stream.action(:toggle_member_list, nil) %>

JavaScript(非同期処理)

+import { StreamActions } from "@hotwired/turbo";
 function toggleMemberList() {
...
 }
+StreamActions.toggle_member_list = function () {
+  toggleMemberList();
+}
 async function addMembers(elm) {
...
       method: 'PUT',
       headers: {
-        'Accept': 'application/json',
+        'Accept': 'text/vnd.turbo-stream.html',
         'Content-Type': 'application/json',
         'X-CSRF-Token': getCsrfToken(),
       },
...
- 変更前
-   1. JSONデータを受信して、
-   2. JavaSctiptでテーブル行を追加。
+    const streamHTML = await res.text();
+    Turbo.renderStreamMessage(streamHTML);
   } catch (err) {

今回のアップデートはAIに協力してもらいました

弊社ではGoogle Workspaceを法人契約しておりGeminiが利用できます。Turboの知識がない状況から今回のアップデートを始めました。当初Webで検索しながら作業を進めていましたけど、(AI初心者ですが)Geminiとやり取りすることでTurboについて効率的に調べることができてとても助かりました。

個人的にはあまりAIに依存したくないのですが、必要に応じてAIを利用することは問題なさそうだと少しだけ認識が変わりました。

My Redmine

こちらの記事もオススメです!
Redmine 7.0ではExcelなどの表を貼り付けられるようになります
Redmine 7.0では、ExcelやGoogleスプレッドシートなどの表をCommonMarkやTextileの表として貼り付けられるようになる予定です。
Redmineリリース前の新機能紹介ブログを始めて6年経ちました
Redmineリリース前の新機能を紹介するブログを毎月書いています。
Redmine 7.0で進む画面デザイン改善
Redmineの次期バージョン7.0では画面デザインの改善が行われます。
自宅のWi-Fiルーターを更新してみた
自宅のWi-Fiが不安定になったのを機に、5年ぶりにルーターを新調。レンタルから買取りへ切り替えたことで、コストを抑えつつ通信速度が従来の約4倍に向上しました。
コードから学ぶ意思決定:ポーカーで考える確率の話
ポーカーアプリの仕組みをヒントに、勝率の計算方法や期待値の考え方を整理し、運だけでない意思決定の面白さをまとめました
ファーエンドテクノロジーからのお知らせ(2026/05/20更新)
My Redmine 2026 夏アップデートのお知らせ(RedMica 4.1対応)
2026年6月からMy Redmine 2026 夏アップデートを実施します。
プロジェクト管理ツール「RedMica」バージョン 4.1.0 をリリース Redmine互換のオープンソースソフトウェア
2026年5月8日(日本時間)、プロジェクト管理ツール「RedMica」バージョン 4.1.0をリリースしました。Redmine互換のオープンソースソフトウェア、今日使える明日のRedmine「RedMica」。
プロジェクト管理のクラウドサービス「My Redmine」の「AIチケット要約」が Azure OpenAI Service との連携に対応
プロジェクト管理のクラウドサービス「My Redmine」の「AIチケット要約」機能が、従来の OpenAI API に加えて、Azure OpenAI Service の API と連携して利用できるようになりました。
Redmineの最新情報をメールでお知らせする「Redmine News」配信中
新バージョンやセキュリティ修正のリリース情報、そのほか最新情報を迅速にお届け