本記事では、Ruby on Railsアプリケーションで使用されているRubyのバージョンを3.1系から3.2系へアップグレードする手順と、その際に発生しがちなエラーの対処法について解説します。
1. Ruby3.2をインストールする
まず、開発環境にRuby 3.2系の最新安定版をインストールします。本記事では執筆時点の3.2.8を例として使用しますが、ご自身の環境でインストール可能な最新版に読み替えてください。
ここではRVM (Ruby Version Manager) を使ったインストール例を示しますが、rbenvやasdf、Dockerなど、他の環境管理ツールでも同様の手順で対応可能です。
▼ ターミナルでRuby 3.2.8をインストール
# bash
rvm install 3.2.8
インストールが完了したら、プロジェクトで使用するRubyのバージョンを切り替えます。
▼ 使用するRubyのバージョンを3.2.8に指定
# Bash
rvm use 3.2.8
正しく切り替わったか、バージョンを確認しておきましょう。
# Bash
ruby -v
#=> ruby 3.2.8p... (バージョン情報が表示されればOK)
2. Gemfileを更新する
次に、アプリケーションのGemfileに記載されているRubyのバージョンを、先ほどインストールしたバージョンに更新します。
# Gemfile
ruby '3.2.8'
バージョンを更新したら、bundle installを実行して、依存関係にあるGemを更新・インストールします。
# Bash
bundle install
インストール後、rails consoleが正常に起動するか確認し、基本的な動作に問題がないか確かめましょう
# Bash
rails console
もしコンソールの起動時にエラーが発生した場合、エラーメッセージに応じて個別に対応が必要です。以下に典型的なエラー例とその対処法を挙げます。
エラー例1: pry gemのundefined methodエラー
~/.rvm/gems/ruby-3.2.8/gems/pry-0.13.1/lib/pry/code.rb:342:in `<class:Code>': undefined method `=~' for class `Pry::Code' (NameError)
このエラーは、pry-byebug gemのバージョンが古い場合に発生することがあります。bundle updateコマンドでpry-byebugを更新することで解消できます。
# bash
bundle update pry-byebug
エラー例2: digest gemのバージョン競合エラー
~/.rvm/gems/ruby-3.2.8/gems/bundler-2.3.6/lib/bundler/runtime.rb:309:in `check_for_activated_spec!': You have already activated digest 3.1.1, but your Gemfile requires digest 3.1.0. Since digest is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports digest as a default gem. (Gem::LoadError)
このエラーは、Ruby 3.2からdigestがデフォルトgemになったことに起因します。Gemfile.lockで古いバージョンが指定されていると競合が発生するため、digest gemを更新して依存関係を解決します。
# Bash
bundle update digest
3. Dockerfileを更新する (Docker利用時)
開発環境やCI/CDでDockerを使用している場合、DockerfileのベースイメージをRuby 3.2系のものに変更します。
# Dockerfile
FROM ruby:3.2.8
Dockerfileを更新したら、Dockerイメージを再構築します。docker composeを使用している場合は、関連するサービスも忘れずに再構築してください。
# docker compose (v2以降) を使っている場合のコンテナ再構築例
docker compose build [サービス名]
4. アプリケーションとテストコードを修正する
Rubyのバージョンアップに伴い、既存のコードで非互換な部分が発生することがあります。
まず、ローカルサーバーを起動して主要な機能を手動でテストします。次に、RSpecやMinitestなどの自動テストを実行し、すべてのテストがパスすることを確認してください。
エラーの内容はアプリケーションの実装に依存しますが、Ruby 3.2へのアップグレードでよく見られる修正点の例をいくつか紹介します。
修正例1: ActiveRecordのscopeでArgumentError
scopeでキーワード引数を使用している箇所で、引数の解釈が厳密になったことによりArgumentErrorが発生する場合があります。
▼ エラーが発生するコード例
class Book < ApplicationRecord
scope :written, ->(author:) { where(author: author)}
end
# 呼び出し側
Book.written(author: 'Natsume Soseki')
ArgumentError (wrong number of arguments (given 1, expected 0; required keyword: author)):
この場合、scopeをクラスメソッドに書き換えることで修正できます。
▼ 修正後のコード例
class Book < ApplicationRecord
def self.written(author:)
where(author: author)
end
end
修正例2: 配列に対して=~を使用した場合のNoMethodError
Ruby 3.1では、配列に対して正規表現マッチ演算子=~を使用するとnilを返していましたが、この挙動は非推奨でした。Ruby 3.2ではこのメソッドが完全に削除されたため、NoMethodErrorが発生します。
▼ バージョンによる挙動の違い
# Ruby 3.1
['a'] =~ /a/
#=> nil (非推奨の警告が出力される)
# Ruby 3.2
['a'] =~ /a/
#=> undefined method `=~' for ["a"]:Array (NoMethodError)
コード内で意図的に配列へ=~を使うケースは稀ですが、POSTパラメータなどが意図せず配列として渡された場合にこのエラーを踏む可能性があります。対象の変数が必ず文字列であることを保証するような修正が必要です。
5. ステージング環境へデプロイする
ローカルでの動作確認とテストが完了したら、ステージング環境へデプロイします。
CapistranoなどのデプロイツールやCI/CDパイプラインの設定でRubyバージョンを指定している箇所があれば、忘れずに更新してください。
デプロイが成功したら、ステージング環境でも主要な機能が問題なく動作するかを改めて手動でテストし、問題があれば修正します。
6. 本番環境へデプロイする
ステージング環境での検証が完了したら、いよいよ本番環境へデプロイします。手順はステージング環境へのデプロイと同様です。
デプロイ後も安心せず、ユーザー影響の大きい重要な機能を中心に最終確認を行いましょう。また、デプロイ後の数日間はエラー監視ツールなどを通じて、予期せぬエラーが発生していないか注意深く監視することをお勧めします。
7. まとめ
Ruby 3.2へのバージョンアップは、依存Gemやアプリケーションコードの状況によって、いくつかの修正が必要になる場合があります。本記事で紹介した手順やエラーの対処法を参考に、一つ一つのステップを落ち着いて慎重に進めてみてください。
