なぜ Rails アップデートで辛い思いをするのか

はじめに
READYFOR 株式会社でバックエンド領域のテックリードをしている @yuji_developer です。
Rails アップデートが辛いとしたらなぜそうなるのか、どうすると良さそうなのかということを書いてみようと思います。
効果のほどは保証できませんので悪しからず……。
Rails アップデート、辛いですか?
Rails アップデートは当然やっていることかと思います。
特別な理由があるアプリケーション以外は基本的にアップデートすべきです。
Rails アップデートが辛いという話はよく耳にします。
私の体感では、辛いと思ったこともありますし、辛いと思わなかったこともありました。
実際にどういうときに辛かったのか、どうしたら良さそうと思っているかを見ていきましょう。
原因1: 取り掛かるのが遅い
Rails アップデートする(必要になった)タイミングまで以下のようなことを続けていると大変になりがちかなと思っています。
- deprecation warning を放置している
- EOL が迫ってからやろうとしている
- 事前に情報収集していない
deprecation warning を放置していて、いざアップデートしようとしたらそこの解消から必要になったり、 EOL が迫ったタイミングで急いで取り掛かろうとして時間がなく大変な思いをしたり、事前に新しいバージョンで何が変わりそうかを調べておらずインパクトの大きい対応への準備が出来ていなかったり……ということあると大変です。
必要になったタイミングでまとめてやろうとすると大変なので、できることは日ごろからコツコツ対応しておくのが良いと思います。
原因2: Rails の標準から外れたことをしている(続けている)
原因1の「取り掛かるのが遅い」とも関連しますが、 Rails のメジャーバージョンアップなどで標準のやり方が変わることがあります。
その時に古いやり方のまま放置していて、新しいやり方に移行出来ていないがために古いやり方のサポートが切れて困ってしまう、というのはありそうです。
アセットパイプラインの標準が変わったものとかがそうですね。
これは早いうちから手を付けて時間に余裕をもって準備していくのが良さそうです。
原因3: 依存関係の問題
Rails アップデート時に依存関係の問題で大変な思いをすることもあるかと思います。
おおむね以下のような原因がありそうです。
- 依存している gem が多い
- 古い gem に依存している
- Rails のコアな部分に手を入れるような gem を利用している
- モンキーパッチをあてている
依存が少なく、古いものは適切に捨てたり更新したりして、 Rails のコアに手を入れるようなものは避け、モンキーパッチも当てていなればおそらく依存関係の問題で大変になることはあまりないのではないでしょうか。
gem の更新は日々の行い、 Rails アップデート時にまとめてやるようなことを避けるのは大事かなと思います。
長く開発しているアプリケーションだと、採用している gem の更新がとまってしまったりすることがありますが、メンテナンスを自分たちでするのか、別の gem なりに移行するのか、そういった判断が必要になります。
だましだまし使うことも出来なくはありませんが、様々なリスクを抱えることになるので避けたほうが良いでしょう。
Rails のコアに手を入れるようなものということ、かつて squeel という gem に強く依存していた時は……。
不具合回避のためのモンキーパッチをあてたりすることもあるとは思いますが、できるだけ issue を起票したり pull request を送ったりしてメインラインに取り込んでもらえるようにすると良さそうです。
原因4: 1回のリリースで済まそうとしている
Rails アップデートは以下のように様々な作業があります。
- アップデート内容の確認および影響調査
- 現在のバージョンで deprecation warning が残っていないかの確認
- 関連 gem の互換性確認および対応
- Rails の gem のバージョン変更
-
rails app:updateの対応 - 新しいデフォルト設定への対応
-
new_framework_defaults_x_y.rbの対応 -
config.load_defaultsの変更
-
- 新しい deprecation warning が出ていないかの確認
1回のリリースですべてやろうとせず段階を踏んでリリースすると良いと思います。
1回のリリースでやろうとすると対応漏れがあったり、予期せぬ不具合で影響範囲の把握が大変になったりします。
また、設定変更の内容によってはロールバックが難しかったり出来なかったりするものもあります。
私がアップデートする場合は十数回以上のリリースに分割することも珍しくありません。
以下のように分割しています。
- バージョンアップ前の deprecatoin warning 解消×必要な回数
- 前回のバージョンアップでゼロになっている場合はスキップ
- 周辺 gem の更新×必要な回数
- バージョンアップ前に事前対応できるような変更×必要な回数
- テストコードを調整したりすることがあります
- rails gem のバージョンアップ&
rails app:update -
new_framework_defaults_x_y.rbの変更×必要な回数- いくつか似たカテゴリーのものをまとめて有効化することはありますがそれなりに分割します
- 特にロールバックできないものは別にしてリリースすることが多いです
-
config.load_defaultsを変更 - 新しい deprecation warning の解消×必要な回数
原因5: 信頼できる CI や E2E テストがない
アプリケーションがすごく小さければまだしも、全機能を手動でテストしたりというのは時間もかかるし大変です。
リリースを分割して安全に行うためにも整備しておくべきでしょう。
原因6: アプリケーションが大きい
アプリケーションが大きいといろいろ目が行き届かないところが出てきます。
これは分割したりして小さくするしかないのですが、一番効果があり現実的だと思ったのは「不要な機能やデッドコード削除してコードベースを小さく保つ」です。
えてしてデッドコードのようなものにつまずきポイントが潜んでいたりするもので、コードベースをスリムに保つのはとても効果があると思っています。
それ以外は……頑張りましょう!
おわりに
結局は必要になったらやるというスタンスよりも、必要になることを見越して早めに準備していく、というのが良いかなと思います。
明日の READYFOR Advent Calendar 2025 は続けて私の記事です。
お楽しみに!
「みんなの想いを集め、社会を良くするお金の流れをつくる」READYFORのエンジニアブログです。技術情報を中心に様々なテーマで発信していきます。 ( Zenn: zenn.dev/p/readyfor_blog / Hatena: tech.readyfor.jp/ )
Discussion