🛤️

Railsバージョンアップ(6.1->7.0)の振り返り

2023/12/21に公開

初めに

ポート株式会社 サービス開発部 Advent Calendar 2023 21日目の記事です。

ポート株式会社サービス開発部に所属している原です。業務では、Railsを用いてバックエンド開発を行なっています。最近の業務でRailsのメジャーバージョンアップを担当して、無事リリースできたので、今回はその振り返りをしていこうと思います。

注意

この記事では全体の流れを振り返る形にしようと思いますので、それぞれを詳しく深ぼることはしない予定です。

実際に行ったバージョンアップの流れ

今回は 6.1.7.2 -> 7.0.8 にバージョンアップしました。実際に行った手順としては下記になります。

  1. Rails7の変更点を調査する
  2. 古いGemをアップデートする
  3. Rails7.0系に対応できていない部分をあらかじめ修正する
  4. Rails6.1.7.xの最新のパッチバージョンまで上げる
  5. Rails7.0.8にバージョンアップ
  6. bin/rails app:updateを実行する
  7. stagingに上げて、全体で確認。
  8. 本番リリース

前提

前提として自分が開発しているプロジェクトでは、下記の条件は満たしているという状況でした。

  • 一定以上のテストカバレッジがある。
  • Dependabotを利用して普段からGemをバージョンアップしている。

バージョンアップの前後で挙動に違いがないことを保証する必要があるためテストカバレッジ率が低い場合はまずはテストを拡充してバージョンアップした方が良さそうです。

それぞれの手順について書いていきます。

1. Rails7の変更点を調査する

こちらは基本的にRailsガイドを参考にしました。
https://railsguides.jp/upgrading_ruby_on_rails.html#rails-6-1からrails-7-0へのアップグレード

2. 古いGemをアップデートする

最新のメジャーバージョンに追随できていないGemを事前にバージョンアップする様にしました。Rails7に対応していないGemのみをバージョンアップする方針でも大丈夫ですが、どのみち今後バージョンアップする必要がある、かつ、普段Depandabotで定期的にバージョンを上げてる影響で、メジャーバージョンアップに追随できていないGemが僅かだったことから、バージョンアップすることにしました。
メジャーバージョンに追随できていないGemの一覧は下記コマンドで出力することができます。
bundle outdated --filter-major

3. Rails7.0系に対応できていない部分をあらかじめ修正する

対応した箇所は主に下記二つです。

  • オートローダーをClassic から Zeitwerk へ移行
  • DEPRECATION WARNING の解消

オートローダーをClassic から Zeitwerk へ移行

Rails7からオートローダーはZeitwerkモードしかないようなので、こちらの移行は必須で行う必要があるようです。Classic から Zeitwerk へ移行はRailsガイドを参考にさせていただきました。
https://railsguides.jp/classic_to_zeitwerk_howto.html

DEPRECATION WARNING の解消

解消した DEPRECATION WARNING は下記になります。

  • Enumerating ActiveModel::Errors as a hash has been deprecated.
  • Merging no longer maintain both conditions, and will be replaced by the latter in Rails 7.0.
  • Calling << to an ActiveModel::Errors message array in order to add an error is deprecated. Please call ActiveModel::Errors#add instead.

下記の DEPRECATION WARNING は個人的にわかりづらかったので、この記事とは別で記事を書こうと思います。
Merging no longer maintain both conditions, and will be replaced by the latter in Rails 7.0.

4. Rails6.1.7.xの最新のパッチバージョンまで上げる

Rails6.1系の最新のパッチバージョンは6.1.7.6です。なので6.1.7.6までバージョンアップしてみて一度CIのスペックが落ちるかどうかみてみます。また、バージョンアップ後にDEPRECATION WARNINGが出た場合は修正します。

5. Rails7.0.8にバージョンアップ

Rails6.1のうちにやるべき対応は終わったので、7.0.8にバージョンアップしていきます。バージョンアップ後はCIのスペックが落ちるかどうかを確認します。複数のテストが落ちていると思うのでこれから修正していきます。

7.0.8にバージョンアップ後に対応したことは下記になります。

  • 外部ホストにリダイレクトする箇所にallow_other_host: trueをつける。
  • datetime型に対してprecisionの制約がつかないようにする。

外部ホストにリダイレクトする箇所にallow_other_host: trueをつける。

こちらはRails7の下記設定を有効化したため、意図して外部ホストにリダイレクトしてる部分に対してallow_other_host: trueをつけるようにしました。
https://github.com/rails/rails/blob/488a7ce188803828c3e7111e23e70108d761c283/railties/lib/rails/application/configuration.rb#L266

datetime型に対してprecisionの制約がつかないようにする。

下記PRの影響でRails7ではデフォルトでdatetime型にprecision: 6の制約がつくようになります。6.1 -> 7.0にバージョンアップした時に本番DBのスキーマと一致しなくなるのを防ぐため、precision: nilを追加し、6.1と7.0でDBスキーマに差分がないように対応しました。
https://github.com/rails/rails/pull/42297

6. bin/rails app:updateを実行する

bin/rails app:updateを実行することで、Rails7.0のデフォルトの設定が記載されてあるファイルであるconfig/initializers/new_framework_defaults_7_0.rbが作成されます。
設定を適用させたい場合はconfig/initializers/new_framework_defaults_7_0.rbの中身を見て、必要なものだけコメントアウトを外します。
また、一括で設定を適用させたい場合は、config/application.rb内でload_default 7.0を追加します。その場合、config/initializers/new_framework_defaults_7_0.rbは削除しても大丈夫です。

new_framework_defaults_7_0.rbの内容に関しては下記記事が参考になりました。
https://qiita.com/SoarTec-lab/items/9832bb89402e452b20bb

7. stagingに上げて、全員で確認

自分が所属しているチームではそれぞれの機能の結合手順書を作成しているので、stagingに上げて全員で動作確認します。基本的にテストが通っていることは確認できているのですが、ユーザーが通常行う操作と同様の操作をすることでバグが出ないことを担保します。

8. 本番リリース

本番にリリースする準備は整ったので、ついに本番リリースします。

終わりに

Railsのバージョンアップをする以前に、Rubyのバージョンアップも担当したのですが、Railsの方がバグが出ることが多く大変でした、、期間的にも2ヶ月ほどかかってしまったのですが、最終的に無事リリースできたのでよかったです!

参考にした記事

Discussion