Rails 7.0.8でdatetimeなカラムの精度が修正された件について

はじめに

少し前に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

カラムの精度に関する変更

7.0.8からマイグレーションファイルのバージョンが6.1の場合、datetimeなカラムの精度は指定なしでマイグレーションされるように修正されました。

github.com

これにより、Rails 7.0.7.2と7.0.8の間でカラムの定義に違いが生じる場合があります。

7.0.7.2以前の7系と7.0.8とでdatetimeなカラムの作成方法が異なります。

  • Rails 7.0.7.2 ... datetime(6) で作成
  • Rails 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のバージョンによるカラム定義の違いに注意する必要があります。
正確なカラムの定義を把握し、適切にマイグレーションを行うことで、問題なくアプリケーションを運用することができます。