9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

クラウドテックをRails6.1からRails7.0へアップグレードしたので、やったことをまとめてみました

Last updated at Posted at 2023-12-08

この記事は クラウドワークスAdvent Calendar 2023の9日目の記事です。

はじめに

株式会社クラウドワークスの@nisyuuです。和食作りに日々励んでいます。
エンジニアとしてクラウドテックというフリーランスと企業をマッチングするエージェントサービスを開発しています。

クラウドテックは2023年11月に、Rails6.1からRails7.0へとアップグレードしました。アップグレード時点でRails7.1がリリースされていましたが、既にRails7.0アップグレードのための変更対応を一通り行いレビュー状態になっていたことと、7.1に対応するためには新たな変更が必要になるため7.0までとしました。

本記事では、Rails6.1からRails7.0へ移行するために行なったことをまとめます。

Rails7.0に依存するgemのアップグレード

GemfileのRailsバージョンを指定している箇所をgem 'rails', '~> 7.0.5.1’に変更します。
次にbundle updateをすることでRails7.0と依存するgemのアップデートが可能となりますが、1時間以上経過しても処理が一向に終わらなかったため、手動で一つ一つ依存gemを確認してアップグレードしました。

手動でアップデートした方法

Railsバージョンをgem 'rails', '~> 7.0.5.1’にした状態で、bundle installをすると、処理が中断し依存するgemをチェックすることができます。

Bundler could not find compatible versions for gem "activemodel":
  In snapshot (Gemfile.lock):
    activemodel (= 6.1.7.3)

  In Gemfile:
    public_activity was resolved to 2.0.2, which depends on
      activerecord (>= 5.0) was resolved to 6.1.7.3, which depends on
        activemodel (= 6.1.7.3)

    rails (~> 7.0.5.1) was resolved to 7.0.5.1, which depends on
      activemodel (= 7.0.5.1)

Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.

activemodelのバージョンが依存関係にあるとわかったので、bundle update --conservative activemodelを実行します。
再びbundle install実行し、Bundler could not find compatible versions for gemが表示されなくなるまで繰り返していきます。

Sprocketsへの依存がオプショナルになった

Rails7.0からsprockets-railsへの依存関係がなくなったため、引き続きSprocketを使用したい場合は別途インストールする必要があります。

アップデートタスクの実行

gemのアップグレードが終わった後に、rails app:updateを実行します。app:updateコマンドは、新しいRailsバージョンで必要となるファイルの新規作成や既存ファイルの変更などが行われます。

ソースコードの変更

手始めはRails 6.1からRails 7.0へのアップグレードを参考にチェック作業を行い、変更対応を入れました。

アップグレードガイド以外の変更必要箇所もあったため、下記にまとめていきます。

ActiveRecord::Base.configurations[Rails.env]が使用できない

ActiveRecord::Base.configurationsがカプセル化されたようで、ActiveRecord::Base.configurations[Rails.env]ActiveRecord::Base.connection_db_config.configuration_hashへと変更する必要がありました。

Tasks::DatabaseTasks.schema_file が削除された

元々、非推奨になっていたTasks::DatabaseTasks.schema_fileがRails7.0で削除されました。代わりに下記コードへと変更しました。

file = ActiveRecord::Tasks::DatabaseTasks.schema_file_type(:sql)
file_path = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, file)

ただし、Tasks::DatabaseTasks.schema_file_typeがRails7.0で非推奨化されてしまったため、他の回避方法があればそちらを選択するのが良さそうです。

to_sがto_fsへと変更

to_sがRails7.0から非推奨となり、to_fsもしくはto_formatted_sが推奨されるようになりました。Rails7.1からto_sは削除となっています。

参考
to_s 👉 to_fsに変更

テストでセッションの値をセットする時はActionController::TestSessionを使用する

Rails7.0にアップグレードしてからallow_any_instance_of(ActionDispatch::Request).to receive(:session).and_return({xxx: yyy})という書き方ができなくなりました。
実際に実行すると、このようなエラーが表示されます。

NoMethodError: undefined method `enabled?' for {xxx: yyy}:Hash

and_returnにハッシュ値の{xxx: yyy}をそのまま入れるのではなく、ActionController::TestSessionでセットした値をand_returnに渡すようにしなければなりません。

mock_session = ActionController::TestSession.new(test_ids: [1, 2, 3])
allow_any_instance_of(ActionDispatch::Request).to receive(:session).and_return(mock_session)

ActiveModel::Errorsがハッシュとして使えなくなった

ActiveModel::Errorsはエラーオブジェクトの配列となりました。

エラーメッセージ

NoMethodError: undefined method `to_sym' for #<ActiveModel::Error attribute=others, type=too_long, options={:count=>4096}>

変更はこのようにする必要があります。

- record.errors.each { |k, v| errors.add(k, v) }
+ record.errors.each { |error| errors.add(error.attribute, error.message) }

ActiveModel::Errors#clearが使えなくなる

非推奨であったActiveModel::Errors#clearが使えなくなり、代わりにActiveModel::Errors#deleteが代替の機能として提供されました。

コードはこのような変更が必要になります。

- errors[:base].clear
+ errors.delete(:base)

mergeを使ってのBETWEEN条件を評価してくれなくなる

同じカラム上で条件を複数マージした時に、マージした条件が維持されず常に後者の条件によって置き換わるようになりました。
複数条件を維持させるには、以下のように一つのmergeで完結させるか、rewhereオプションを使うことで可能なようです。

relation = Author.all
- relation = relation.joins(:book).merge(Book.where(published_at: start_published_at..)) if start_published_at.present?
- relation = relation.joins(:book).merge(Book.where(published_at: ..end_published_at)) if end_published_at.present?
+ relation.joins(:book).merge(Book.where(published_at: start_published_at.presence..end_published_at.presence))

rewhereについてはRuby on Rails 7.0 リリースノートを参照ください。

検証作業

Rails7.0の変更対応を終え、CIも無事に通るようになったところで、通常のコードレビューに加えドッグフーディングやウォークスルーを実施しました。
ドッグフーディングとは、開発したものを実際に自社組織内で使ってみることを意味します。今回の場合だと、Rails7.0環境の含まれるブランチを各エンジニアに取り込んでもらい、実際にRails7.0上で作業してもらうことでドッグフーディングを実施しました。
ウォークスルーは、評価対象のプロセスを実際に体験をすることを指します。評価対象は影響範囲のある箇所がメインになります。Rails7.0アップグレードはシステム全体に影響があるものなので、システム上のユーザーがよく使用する機能を中心に幅広くウォークスルーを行いました。

おわりに

チームのサポートと入念にチェックを行っていたおかげで、リリースは何事もなく終えられました。

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?