0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rails schema.rbでbigintとintegerの差分が出る問題

0
Posted at

背景

Rails 8.0 + SQLite3 環境でチーム開発をしていたら、自分は何もマイグレーションを変更していないのに db/schema.rb の外部キーカラムが bigint から integer に変わる差分が出た

# before
t.bigint "user_id"

# after
t.integer "user_id"

「DBのデータ壊れた?」と焦ったので調べた

結論

DB上のデータは一切変わっていない。sqlite3 gem のバージョン違いによって schema.rb への翻訳ルールが異なるだけ

対処法は Gemfile で sqlite3 gem のバージョンを明示すること

# Gemfile
gem 'sqlite3', '~> 2.9'

そもそも schema.rb はどう生成されるのか

schema.rb は手で書くファイルではなく、マイグレーション実行時にローカル DB の状態を読み取って自動生成されるファイル

マイグレーション実行
  → ローカルSQLiteにカラム追加
  → sqlite3 gemがDBスキーマを読み取り
  → schema.rb に翻訳して書き出す ← ここで差が出る

つまり schema.rb の内容は「DB の実態」と「gem の翻訳ルール」の掛け算で決まる

なぜ bigint と integer の差分が出るのか

SQLite には BIGINT 型が存在しない。内部的には外部キーも含め全て INTEGER として保存される

問題は sqlite3 gem がこの INTEGERschema.rb に書き出す際の翻訳ルールがバージョンによって違うこと

sqlite3 gem のバージョン 翻訳結果
あるバージョン INTEGERt.bigint "user_id"
別のバージョン INTEGERt.integer "user_id"

DB上のデータは全く同じなのに、gem の翻訳ルールが違うため schema.rb のテキストだけが変わる

なぜチーム内で差が出るのか

Gemfile でバージョン指定なし(例: gem 'sqlite3')だと、Gemfile.lock で固定されていても、過去に別バージョンで生成された schema.rb との差分が残ることがある

チームメンバーが異なるタイミングで bundle install していると、ローカルにインストールされている gem のバージョンが微妙にずれる可能性がある

対処法

Gemfile で sqlite3 gem のバージョンを明示して、チーム全員の翻訳ルールを揃える

gem 'sqlite3', '~> 2.9'

また、schema.rb をコミットする際は 自分のマイグレーション分以外の差分が含まれていないか を必ず git diff db/schema.rb で確認する

感想

  • 「DB のデータは同じなのに gem の翻訳ルールだけが変わる」という構造がわかると、もう怖くない
  • schema.rb 関連の問題に遭遇するたびに思うけど、「自動生成ファイルの差分はまず生成元を疑え」は鉄則やな

参考

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?