💡

Rails7からRails8へアップデートさせるの巻

2024/12/08に公開

はじめに

こんにちは😃
記事を読んでくださりありがとうございます。
初投稿となります。

今回のテーマはタイトルに書いたように、Railsを7から8へアップデートさせてみました!
最近はRails8がリリースされたのと、業務でもアップデートに
取り組むことがあったのでまとめる良い機会だと思い、記事にしてみました。

対象読者

Railsのアップデートに興味がある方

バージョン情報

MacOs Sonoma 14.5
Docker 27.3.1
Ruby 3.3.5
Rails 7.2.2

Dockerを使っています。

状態 Ruby Rails
Before 3.3.5 7.2.2
After 3.3.6 8.0.0

手順

  1. Rails以外のgemを最新にする
  2. Rubyのバージョンを最新にする
  3. Railsをバージョンアップする
  4. rails app:updateタスクを実行する
  5. config.load_defaultsとnew_framework_defaults_x_x.rbの設定
  6. Railsが正常に起動することを確認する

伊藤さん式を参考に対応しました。
https://qiita.com/jnchito/items/0ee47108972a0e302caf

違う点はDocker環境で実行している点です。
アップデート用のブランチへチェックアウトしてスタート!

Rails以外のgemを最新にする

  1. Dockerとコンテナを起動
  2. Gemの状態を確認
  3. Gemのバージョンをアップデート
  4. コンテナ再ビルド

まずはDockerのコンテナ内にアクセス。
Docker exec -it コンテナ名 bash

  1. Gemの状態を確認
    bundle outdated
    を実行してGemの状態をチェックします。

  2. Gemのバージョンをアップデート
    ここは環境によって差がでますが
    rubyとrailsのバージョンはしっかりと固定しつつ、
    bundle update を使いこなしてGemをアップデートさせてください!
    私の場合は個人開発アプリなのですぐにでしたが参考に...

Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.3.5"
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'
gem "rails", "7.2.2"
# Use sqlite3 as the database for Active Record
gem "pg"
# Use Puma as the app server
gem "puma"
# Use SCSS for stylesheets
gem "sass-rails"
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem "turbolinks"
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem "jbuilder"
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Use Active Storage variant
# gem 'image_processing', '~> 1.2'
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem "byebug", platforms: [:mri, :mingw, :x64_mingw]
end
group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem "web-console"
  # Display performance information such as SQL time and flame graphs for each request in your browser.
  # Can be configured to work on production as well see: https://github.com/MiniProfiler/rack-mini-profiler/blob/master/README.md
  gem "rack-mini-profiler"
  gem "listen"
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem "spring"
  gem "rubocop", require: false
  gem "rubocop-performance", require: false
  gem "rubocop-rails", require: false
  gem "rubocop-minitest", require: false
  gem "rubocop-packaging", require: false
  gem "rubocop-rspec"
end
group :test do
  # Adds support for Capybara system testing and selenium driver
  gem "capybara"
  gem "selenium-webdriver"
  # Easy installation and use of web drivers to run system tests with browsers
  gem "webdrivers"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem "devise"
gem "carmen-rails", git: 'https://github.com/Studiosity/carmen-rails.git'
gem "dotenv-rails"
gem "kaminari"
gem "devise-i18n"
gem "devise-i18n-views"
gem "jquery-rails"
group :production do
end
gem "net-smtp"
gem "net-pop"
gem "net-imap"
gem 'bootstrap'
gem 'font-awesome-sass'
  1. コンテナ再ビルド
    ここで一旦コンテナをダウンさせて、再ビルドさせます。
    Dockerfileを修正していませんが、Gemのアップデートによる影響で起動に問題ないのか確認します。

Rubyのバージョンを最新にする

再ビルドが完了したら、今度はRubyのバージョンアップをします。

  1. Gemfileを更新
  2. Dockerfileを更新
  3. bundle install
  4. コンテナ再ビルド

目指すバージョンへ一気に上げるのではなく
パッチバージョン→マイナーバージョン→メジャーバージョンの順で対応します。
※パッチバージョンのみ上げてます。

  1. Gemfileを更新
Gemfile
+ ruby "3.3.6"
- ruby "3.3.5"
  1. Dockerfileを更新
Dockerfile
# Rubyのバージョンを3.3.6へ
+ FROM ruby:3.3.6-alpine
- FROM ruby:3.3.5-alpine
  1. 変更したらbundle installを実行します。
  2. コンテナ再ビルド
    ここでまたコンテナをダウンさせてDockerを再ビルドさせます。
    Docker compose build --no-cache

Railsをバージョンアップする

再ビルドが完了したら、今度はRailsのバージョンアップをします。

  1. Gemfileを更新

  2. bundle update rails

  3. コンテナ再ビルド

  4. rails app:updateタスクを実行

  5. Gemfileを更新

Gemfile
-gem "rails", "7.2.2"
+gem "rails", "8.0.0"
  1. bundle update rails
    bundle update railsを実行

  2. コンテナ再ビルド
    ここでまたコンテナをダウンさせてDockerを再ビルドさせます。

  3. 次にrails app:updateタスクを実行します。

terminal
/abboo # rails app:update
  identical config/boot.rb
    exist config
  conflict config/application.rb
Overwrite /abboo/config/application.rb? (enter "h" for help) [Ynaqdhm] d
--- /abboo/config/application.rb
+++ /abboo/config/application.rb20241117-201-2aj3q7
@@ -10,7 +10,12 @@
  class Application < Rails::Application
   # Initialize configuration defaults for originally generated Rails version.
   config.load_defaults 7.2
-  config.paths.add 'lib', eager_load: true # libファイルの読み込み
+
+  # Please, add to the `ignore` list any other `lib` subdirectories that do
+  # not contain `.rb` files, or that should not be reloaded or eager loaded.
+  # Common ones are `templates`, `generators`, or `middleware`, for example.
+  config.autoload_lib(ignore: %w[assets tasks])
+
   # Configuration for the application, engines, and railties goes here.
   #
   # These settings can be overridden in specific environments using the files
@@ -18,7 +23,5 @@
   #
   # config.time_zone = "Central Time (US & Canada)"
   # config.eager_load_paths << Rails.root.join("extras")
-  config.i18n.default_locale = :ja
-  config.time_zone = "Tokyo"
  end
 end

上書き更新されるファイルは次のように対応方法を質問されるので、 Y/n/a/q/d/hのいずれかのキーを入力します。

config.load_defaultsとnew_framework_defaults_x_x.rbの設定

既存のRailsアプリを新しいバージョンにアップデートするために rails app:update コマンドを使うと、 config/initializers 以下に new_framework_defaults_8_0.rb のようなファイルが作成されます。
最後にconfig/new_framework_defaults_8_0.rbとapplication.rb修正します。

  1. Rails 8.0にアップグレードし、rails app:updateコマンドを実行
  2. load_defaultsは7.2のままで、new_framework_defaults_8_0.rbのコメントを1つずつ外し動作確認する
  3. new_framework_defaults_8_0.rbのコメントを全部外しても問題が起きなければ、load_defaultsを8.0に変更し、new_framework_defaults_8_0.rbを削除する
new_framework_defaults_8_0.rb
# Be sure to restart your server when you modify this file.
#
# This file eases your Rails 8.0 framework defaults upgrade.
#
# Uncomment each configuration one by one to switch to the new default.
# Once your application is ready to run with all new defaults, you can remove
# this file and set the `config.load_defaults` to `8.0`.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
###
# Specifies whether `to_time` methods preserve the UTC offset of their receivers or preserves the timezone.
# If set to `:zone`, `to_time` methods will use the timezone of their receivers.
# If set to `:offset`, `to_time` methods will use the UTC offset.
# If `false`, `to_time` methods will convert to the local system UTC offset instead.
#++
Rails.application.config.active_support.to_time_preserves_timezone = :zone
###
# When both `If-Modified-Since` and `If-None-Match` are provided by the client
# only consider `If-None-Match` as specified by RFC 7232 Section 6.
# If set to `false` both conditions need to be satisfied.
#++
Rails.application.config.action_dispatch.strict_freshness = true
###
# Set `Regexp.timeout` to `1`s by default to improve security over Regexp Denial-of-Service attacks.
#++
Regexp.timeout = 1

今回は3つの変更があったようです。1つずつコメントアウトして新しい挙動がアプリケーションに問題ないか確認していきます。

  1. active_support.to_time_preserves_timezone
    Rails.application.config.active_support.to_time_preserves_timezone = :zone
    この設定は、to_time メソッドがどのタイムゾーン情報を保持するかを決定します。

  2. action_dispatch.strict_freshness
    Rails.application.config.action_dispatch.strict_freshness = true
    HTTP ヘッダーの If-Modified-Since と If-None-Match に基づいてリソースが変更されたかどうかを判断する際の挙動を制御します。

  3. Regexp.timeout
    Regexp.timeout = 1
    正規表現の処理にタイムアウトを設定します。
    デフォルトで 1秒 に設定されます。

全ての設定を問題なく適用できた場合は、このファイルを削除し、config/application.rb の config.load_defaults を 8.0 に変更します。

application.rb
class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
+   config.load_defaults 8.0
-   config.load_defaults 7.2

Railsが正常に起動することを確認

最後にコンテナをダウンさせて再度アップさせます(再ビルドは不要)
あとはコンテナ内にアクセスし、Rails cが起動するかアプリケーションが動くかどうか確認して
問題がなければローカルでの作業が終了です。
このあとはテスト環境→本番環境にデプロイして問題が無いか確認です。

まとめ

最後まで読んでいただきありがとうございました。
今回はDocker環境を使用していたこともあり、修正すべき項目が多く、想定以上に工数がかかってしまいました。

特に反省すべき点として、テスト項目を事前に用意していなかったことが挙げられます。次回はRSpecなどを導入し、テストをしっかり実施したうえで開発を進めることで、よりスムーズに作業を進められるよう改善したいと思います。

この記事が同様の課題に取り組んでいる方の参考になれば幸いです。それでは、また次の記事でお会いしましょう!

参考資料

https://qiita.com/jnchito/items/0ee47108972a0e302caf
https://qiita.com/jnchito/items/cce3b2795e1c66735310
https://techtechmedia.com/ruby-rails-upgrade/

Discussion