本番環境をRails6.0からRails7.0へアップグレード


今回、自社サービスの本番環境を Rails 6.0 から Rails 7.0 へアップグレードしましたので、その備忘録として書き留めておきたいと思います。

サービスを展開してるサイトですが、リクエストベースで1分間に約6000リクエスト程度が発生するサイトになります。
そこへ、Ruby 3.1.1 + Rails7.0.2.2 (作業時点の最新)の導入を行いました。

アップグレードの手順自体は、いろいろな方がQiita等で説明されていると思いますので、ここでは、実際に対応が必要だったポイントを残しておきたいと思います。

## 対象
・同じくRailsのアップグレードと戦うのエンジニアの方
・アップグレードしないとダメだよねー。と思いつつも、華麗にスルーされている方

## 手順
基本的な進め方は「[Rails アップグレードガイド](https://railsguides.jp/upgrading_ruby_on_rails.html "Rails アップグレードガイド")」をそのまま参考にさせて頂きました。
結果、問題なくアップグレードでき、本番環境へリリース出来ましたので、まだ読まれていない方は一読される事をおすすめいたします。

全体の流れとしては、「[Rails6.0 から Rails6.1](https://railsguides.jp/upgrading_ruby_on_rails.html#rails-6-0%E3%81%8B%E3%82%89rails-6-1%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89 "Rails6.0 から Rails6.1") 」へアップグレードした後、「[Rails6.1 から Rails7.0](https://railsguides.jp/upgrading_ruby_on_rails.html#rails-6-1%E3%81%8B%E3%82%89rails-7-0%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89 "Rails6.1 から Rails7.0") 」へアップグレードする、2ステップで実施しました。
実は、いきなり Rails 7.0 へアップグレードにもトライしてみたのですが、1つ1つのエラーを追うのが大変になり、戦意喪失。
急がば回れで、2ステップで進めました。



## Rails 6.0 から Rails 6.1

```rails app:update```コマンドでアップグレード実施すると「new_framework_defaults_6_1.rb」というファイルが、「config/initializers/」フォルダに作成されます。

このファイルには、Rails 6.0と6.1の間で変化のあった設定が書かれていて、変更することで以前の動作に合わせることができるようになっています。

そこで、自動テストを回したり、手動でサイトを操作することでエラーの発生を確認し、以前の動作に戻す設定を探すことで、必要な対応ポイントの洗い出しを行いました。

```
エラーを確認
↓
該当のオプション設定を探し。設定を変更
↓
無事プログラムが動くことを確認
```



### urlsafe_csrf_tokens

対応が必要となった1つ目のケース
CSRFトークンのエンコード方式が、base64からurlsafeのbase64に変更となりました。

最初は、さくっとurlsafeのbase64へ切り替えればよいと思ったのですが、Rails 6.0 -> Rails 7.0 は大丈夫でも、Rails 7.0 -> Rails 6.0 に戻すとエラーとなることが解りました。
Railsアップグレードに伴うリスク回避のため、問題発生時にすぐ旧環境へ切り戻しが出来る状態を残しておきたかったので、今回は動作変更のオプションで、以前の動作同じ設定とし本番リリースをいたしました。

とはいえ、次のような、`DEPRECATION WARNING` が出ていますので、頃合いを見て設定を変更したいと思います。
```
DEPRECATION WARNING: Non-URL-safe CSRF tokens are deprecated. Use 6.1 defaults or above. 
```


動作変更のオプションはこちら
```new_framework_defaults_6_1.rb
# This change is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 6.1.
# Rails.application.config.action_controller.urlsafe_csrf_tokens = true

# false をセットすることで以前の設定となる
Rails.application.config.action_controller.urlsafe_csrf_tokens = false
```

### form_with_generates_remote_forms

対応が必要となった2つ目のケース。
Rails 6.0 では `form_with` を使うと`data-remote = "true"` が付与されていましたが、こちらが変更となりました。

そこで、全ての `form_with` に `local: false` を追加する修正を行い、`data-remote = "true"` が付与されるように変更しました。

動作変更のオプションはこちら
```new_framework_defaults_6_1.rb
# Make `form_with` generate non-remote forms by default.
# Rails.application.config.action_view.form_with_generates_remote_forms = false

# true をセットすることで以前の設定となる
Rails.application.config.action_view.form_with_generates_remote_forms = true
```




## Rails 6.1 から Rails 7.0

```rails app:update```コマンドでアップデートを実施すると「new_framework_defaults_7_0.rb」
というファイルが、「config/initializers/」フォルダに作成されます。

Rails 6.1の時と、同じ手順で進めていくのですが、上の修正でほとんど解決出来ていたようで、ここでは特に修正を入れること無く対応が完了しました。


## 最後に

Rails 7.0 に合わせて、import-mapの導入や、今までassetに書いていたjavascriptも継続して使えるよう、import-map + sprockets-rails の併用なども行いました。


また、機会がありましたらご紹介させて頂きます。