背景
Rails6系はActive SupportとSecurity Supportが切れています。早急にRails7系にアップグレードする必要があがります。
しかしながら、Rails6系からRails7系へのバージョンアップはメジャーバージョンアップということもあり、細かな設定の変更に時間がかかりました。
そこで本記事では、効率的なバージョンアップを実現できるように、僕自身のアップグレード方法を記録として残します。アプグレードしたWebアプリは、「Touringmate」です。
開発中のアプリによっては、追加でGemのアップデートが必要になるかもしれませんが、参考になれば嬉しいです。
※2024年12月現在で安定版であるRails7.2.2は、Ruby3.1.0以上を必要とします。Rubyのアップグレードをお忘れなく!
バージョン
Ruby:3.2.4
Rails:6.1.7.7→7.2.2
bundler:2.5.3
node:22.11.0
npm:10.9.0
yarn:4.0.0
webpack:5.96.1
shakapacker:8.0.0
開発環境
macOS: Sonoma14.7.1
エディター: Cursor@VSCode
Rails6系から7系へのアップグレード手順
1. Gemの更新
Gemfile内のRailsのバージョンを更新します。
#Gemfile
gem "rails", "~> 7.2.0"
#ターミナル
bundle update rails
2. JavaScriptパッケージの更新
package.json内のRails関連パッケージを最新バージョンに更新します。
package.jsonを確認したところ、「@rails/actioncable」「@rails/activestorage」「@rails/ujs」がバージョンアップ対象でした。
以下のコードで最新バージョンに更新します。
yarn up "@rails/actioncable@latest"
yarn up "@rails/activestorage@latest"
yarn up "@rails/ujs@latest"
また、Webアプリのフロントエンドを一部Reactで実装しているため、「react」と「react-dom」も最新バージョンに更新します。
yarn up react@latest
yarn up react-dom@latest
念のため、全体の依存関係を再インストールします。
yarn install
3. オートローダーのClassicモードからZeitwerkモードへの移行
Rails 6からRails 7にアップグレードする際、オートローダーをClassicモードからZeitwerkモードに移行します。
config/application.rbファイルに「config.load_defaults 7.0」を追加します。
# config/application.rb
module DriveMate1
class Application < Rails::Application
config.load_defaults 7.0
config/environments/development.rbで以下の設定を確認または追加し、自動読み込みが有効であることを確認します。
# config/environments/development.rb
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
4. Devise関連のアップデート
WebアプリでDeviseを使用している場合は、関連のgemを最新バージョンに更新します。
僕の場合は「Devise」「Devise Token Auth」「OmniAuth」が対象でした。
4-1. Deviseの更新
ターミナルで「bundle update devise」を実行、Deviseのバージョンを4.9.4に更新しました。
# ターミナル
bundle update devise
4-2. Devise Token Authの更新
Rails7のDevise Token Authは、GitHub上でサポートされています。したがって、GitHubリポジトリから直接Devise Token Authをインストールするように設定します。
# Gemfile
gem 'devise_token_auth', github: 'lynndylanhurley/devise_token_auth'
# ターミナル
bundle install
4-3. OmniAuthの更新
OmniAuthのバージョン2.0以上は、Ruby 3.0+をサポートしています。OmniAuthのバージョンを2.0以上に更新します。
5. listen gemの追加
「rails s」でサーバーを立ち上げようとした結果、「listen is not part of the bundle」というエラーが発生しました。
以下のコードで、listen gemを追加します。
# Gemfile
gem 'listen', '~> 3.7'
# ターミナル
bundle install
React構成箇所の反映
Shakapacker導入済みのRails6系を7系にバージョンアップする場合、以下のエラーが発生するかもしれません。
Uncaught TypeError: __webpack_require__(...).start is not a function
at ./app/javascript/application.js (application.js:6:1)
at __webpack_require__ (bootstrap:19:1)
at __webpack_exec__ (Touring_group_list.js:141:1)
at Touring_group_list.js:141:1
at __webpack_require__.O (chunk loaded:25:1)
at Touring_group_list.js:141:1
at webpackJsonpCallback (jsonp chunk loading:36:1)
at application.js:1:73
config/webpack/webpack.config.js(またはconfig/webpack/environment.js)に、React用Babelローダーを設定します。
# config/webpack/webpack.config.js
module: {
rules: [
{
test: /\.jsx?$/, // .js または .jsx ファイルを対象
exclude: /node_modules/, // node_modules ディレクトリは除外
use: {
loader: 'babel-loader', // Babelローダーを使用
options: {
presets: ['@babel/preset-env', '@babel/preset-react'], // React用プリセットを指定
plugins: [isDevelopment && 'react-refresh/babel'].filter(Boolean), // 開発環境でFast Refresh有効化
},
},
},
],
},
以下のパッケージがインストールされているかを確認します。
・@babel/core
・@babel/preset-env
・@babel/preset-react
・babel-loader
インストールされていない場合は、以下のコードを実行して、インストールします。
yarn add @babel/core @babel/preset-env @babel/preset-react babel-loader
app>javascript?application.jsファイルの「require("@rails/ujs").start()」でエラーが発生するかもしれません。
その場合は、「require("@rails/ujs").start()」を以下のコードに書き換えます。
# app>javascript>application.js
import Rails from "@rails/ujs"
Rails.start()
@rails/ujsのバージョンが古い場合は、以下のコードで最新バージョンに更新します。
yarn add @rails/ujs@latest
なお、Rails7から利用可能となった「Turbo Drive」を有効化すると、React構築箇所が画面に反映されないかもしれません。
(画面をリロードすると、React構築箇所が画面に反映されます)
これは、「Turbo Drive」による画面読み込みの高速化(Reactコンポーネントの読み込み遅延)が原因と考えられます。
したがって、app>javascript?application.jsファイルでは、「@hotwired/turbo-rails」をインポートしてはいますが、「Turbo.session.drive = false;」で「Turbo Drive」も無効化しています。
# app>javascript>application.js
import "@hotwired/turbo-rails";
// Turbo Driveを無効化
Turbo.session.drive = false;
ActiveSupport::Deprecation.warnへの対処
「rails s」でサーバーが立ち上がったは良いものの、「ActiveSupport::Deprecation.warn」というエラーが頻繁に発生しました。
Rails7.2.2では、「ActiveSupport::Deprecation.warn」メソッドが削除されたためにエラーが発生します。
以下に僕が直面した「ActiveSupport::Deprecation.warn」への対処方法をまとめます。
ActiveSupport::Deprecation.warnの置き換え
Rails 7.2以降では、独自のデプリケーションオブジェクトを使用する必要があります。
config>initializers>deprecation.rbファイルを作成、以下をコーディングします。
# config>initializers>deprecation.rb
# 独自のデプリケーションオブジェクトを作成
MyAppDeprecator = ActiveSupport::Deprecation.new('2.0', 'MyApp')
# 警告を出す
MyAppDeprecator.warn('このメソッドは非推奨です。')
CarrierWaveに対する対処
「fog_provider=': private method warn' called for ActiveSupport::Deprecation:Class (NoMethodError)」というエラーが発生しました。
carrierwave.rbファイルから、以下のコードを削除しました。
# config.fog_provider = 'fog/aws'
「private method 'warn' called for ActiveSupport::Deprecation:Class」というエラーが発生しました。
以下のコードで、CarrierWaveを最新バージョンに更新しました。
# Gemfile
gem 'carrierwave', '~> 3.1.0.beta'
# ターミナル
bundle update carrierwave
web_consoleに対する対処
「web_console_permissions': private method warn' called for ActiveSupport::Deprecation:Class (NoMethodError)」というエラーが発生しました。
web_consoleを最新バージョンに更新しました。
# Gemfile
gem 'web-console', '~> 4.2.1'
# ターミナル
bundle update web-console
まとめ
本記事では、Rails6系から7系へのアップグレード手順について、詳細に解説しました。
Rails7系は新機能の追加により、より強固で高性能なフレームワークとなっていますが、アップグレードには多くのステップが必要です。特にGemやJavaScriptパッケージの更新、オートローダーの移行、React構成箇所の調整など、各段階でエラーや互換性の問題に対処する必要がありました。
また、Devise関連のGemやActiveSupport::Deprecation.warnの変更に対応することで、安定した動作環境を構築するための工夫も必要でした。これらの経験や手順が、読者の方々が効率的にアップグレードを進める際の参考になれば幸いです。
Railsのアップグレードは一度の作業で完結するものではなく、テストやデプロイ後も注意深く運用を続ける必要があります。本記事を通じて、アップグレードのプロセスがスムーズに進むことを願っています。