Rails 7にアップデートした

rails 6.1のアプリケーションを7.0にアップデートした。

元々はrails 5.1で作成したアプリケーションなのだが、6.0から6.1にあげたときに rails app:updateを実行し忘れていたことに気づいた。が、特に問題なく動いていたようだ。。。

アップデート手順

bundler自体のアップデート

必要ないかもしれないが念のため最新にしておく

$ bundle update --bundler

Gemファイルの修正

-  gem 'rails', '~> 6.1.4', '>= 6.1.4.1'
+  gem 'rails', '~> 7.0.0'

rails app:updateの実行

$ THOR_MERGE=vimdiff ./bin/rails app:update

THOR_MERGEにはお好きなマージツールを設定してください

実行すると変更を加えたファイルがconflictと表示されてどうするか聞かれる。

  • yで新しいファイルに上書き
  • nで既存のファイルを残す
  • dでdiffを見れる
  • mでマージツールを起動する

diffを見つつ、いい感じに作業してください

要らんマイグレーションの削除

active storageを使ってないのにactive storage用のマイグレーションファイルが作られてしまったので削除

db/migrate/20220101144141_add_service_name_to_active_storage_blobs.active_storage.rb
db/migrate/20220101144142_create_active_storage_variant_records.active_storage.rb
db/migrate/20220101144143_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb

このマイグレーションが作られてしまうのは config/application.rbrailsの全機能が有効になっているから

require "rails/all"

ただactive storageの機能をロードしても使わなければactive storage用テーブルがなくても問題ないようだ。この辺は使わないなら多少ぶっ壊れていてもOKという動的言語の軽いノリである。なので作成されたマイグレーションは削除してしまって良い

active storageを読み込まないようにするには、require "rails/all" を以下のように置き換える

require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
# require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_mailbox/engine"
require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
require "rails/test_unit/railtie"

この状態でrails app:updateするとマイグレーションファイルが作られなくなる

※ config/storage.ymlは残しておくこと、消すと本番起動できなくなる(development modeでは遅延ロードされるのでactive storageを使わなければ問題ないが、production modeでは起動時にロードするため落ちる)

デフォルト値のバージョンを7.0にする

これは無理にやる必要はないのだが、rails 5.1の時からそのままなので、そろそろ直しておいた方が良さそうな気がした。

config/application.rbconfig.load_defaultsを修正

-    config.load_defaults "5.1" 
+    config.load_defaults "7.0"

こうすると各設定項目のデフォルト値がrails 7.0のものになる。デフォルト値が変わることで挙動も変わるので十分にテストして問題ないか確認する。

rails 7.0で変更されたデフォルト値は

config/initializers/new_framework_defaults_7_0.rb

というファイルに記述されている。説明は英語だがコメントされたコード部分を見ればなんとなくわかるだろう。本来はこのファイルの設定項目のコメントを1つずつ外してテストし、全ての設定項目で問題ないことが確認できたら晴れてconfig.load_defaults7.0にする、というものなのだが、自分のアプリは小規模なので雑に修正している。

私のアプリでは、外部サイトへのリダイレクトを不許可にするRails.application.config.action_controller.raise_on_open_redirects という設定に引っかかった。別ドメインへリダイレクトしているredirect_toメソッドは一か所しかないので、そのオプションに { allow_other_host: true }を付ける修正をおこなって解決

(なお、6.1アップデート時のrails app:updateの実行忘れは new_framework_defaults_6_1.rb が無かったので気づいた)

webpackerをimportmapに置き換え・・・は見送り

webpackerはJS管理ツールのデフォルトではなくなったらしい(webpackerを選択することもできる)。今時のシステム構成だとバックエンドはJSONでデータを返すAPIサーバとし、reactやvueでフロントを作成するのが多いので、Railsのデフォルトからwebpackerを外すという決定は理解できる。

DHHはhotwireなどを作ってフロントもRailsに統合し続けたいようだが、そこまで頑張らなくてもいいんじゃないかなとは思う。ただ、RailsにはWeb-DBアプリケーションのプロトタイピングツールという側面があるため、hotwireのような選択肢も必要なのかもしれない。バックエンド畑で育った人間がプロトタイピングにreactはちょっと重い。

まあ、いずれにせよwebpackerが廃止されるわけではないので、一旦そのままにしておくことにした。