はじめに
少し前にRails 7.0.8がリリースされましたが、その前のバージョンである7.0.7.2でマイグレーションした結果のdb/schema.rb
が異なるということについて質問されたので、金曜夜に解説した内容を文章にまとめたものになります。
前提
- Rails 7.0.7.2 -> 7.0.8へアップグレードした時に起きた現象
- DBはMySQL
- 発生する現象は、6.1なマイグレーションファイルでchange_columnしているdatetimeなカラムのprecisionが
db/schema.rb
についたりつかなかったりする
TL; DR
- Rails 7.0.7.2と7.0.8とで、6.1なマイグレーションファイルかつ、chnage_columnされたdatetimeなカラムの扱いが変わる
- カラムの定義に違いが生じる原因は、 Fix 6.1 change_column setting datetime precision [7-0-stable] by skipkayhil · Pull Request #49006 · rails/rails · GitHub の変更により、7.0.8からは精度指定なしのdatetimeが作成されるようになった
- マイグレーションが実行された時のRailsのバージョンによって、DBスキーマ自体が異なるので確認した方が良いかもしれない
- バージョン間の差分でどちらのバージョンでマイグレーションされたDBなのかによって
db/schema.rb
の結果が異なる
カラムの精度に関する変更
7.0.8からマイグレーションファイルのバージョンが6.1の場合、datetimeなカラムの精度は指定なしでマイグレーションされるように修正されました。
これにより、Rails 7.0.7.2と7.0.8の間でカラムの定義に違いが生じる場合があります。
7.0.7.2以前の7系と7.0.8とでdatetimeなカラムの作成方法が異なります。
そのため、7.0.8の修正が入る前の7系のRailsと、7.0.8のRailsのどちらのタイミングでマイグレーションしたかによって、カラムの定義が異なる可能性があります。
以下のようなマイグレーションファイルが定義されている場合、それぞれのバージョンでスキーマにどういった影響があるのかを確認してみます。
class Hoge< ActiveRecord::Migration[6.1] def change change_column :users, :inactive_at, :datetime, default: '2023-10-27 14:50:04' end end
それぞれのバージョンでマイグレーションした場合のテーブル定義は以下のようになっており、inactive_at
のdatetimeの精度指定が異なることが分かります。
# Rails 7.0.7.2でマイグレーションした場合のdatetimeなカラムの定義 > show create table users \G; *************************** 1. row *************************** Table: users Create Table: CREATE TABLE `users` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `inactive_at` datetime(6) DEFAULT '2023-10-27 14:50:04.000000', `created_at` datetime(6) NOT NULL, `updated_at` datetime(6) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 # Rails 7.0.8でマイグレーションした場合のdatetimeなカラムの定義 > show create table users \G; *************************** 1. row *************************** Table: users Create Table: CREATE TABLE `users` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `inactive_at` datetime DEFAULT '2023-10-27 14:50:04', `created_at` datetime(6) NOT NULL, `updated_at` datetime(6) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 1 row in set (0.000 sec)
カラム定義の違いの影響
このカラム定義の違いが、実際のアプリケーションにどのような影響を与えるのでしょうか?
例えば、7.0.7.2でマイグレーションしていたAさんの環境と、7.0.8にアップグレードした後にデータベースを作り直したBさんの環境とでは、rails db:schema:dump
の結果が異なります。
この挙動によっては、ローカルだけではなく特定のテスト環境や場合によっては本番環境を含めて、書く環境ごとにdatetimeの精度が異なるという可能性がありえます。
おわりに
本記事では、Rails 7.0.8と7.0.7.2の間でdatetimeなカラムのschema.rbが異なることについて解説しました。
アプリケーション開発やマイグレーションを行う際には、Railsのバージョンによるカラム定義の違いに注意する必要があります。
正確なカラムの定義を把握し、適切にマイグレーションを行うことで、問題なくアプリケーションを運用することができます。