(Rails)実務でmigrateファイルを扱って調べたこと諸々。add refence vs add foreign_keyなど
実務でmigrateファイルを新規追加したのでその時に調べたことや試したことをメモしておく。
migrateファイルは個人開発でしか書いたことがなかったし、それも数年前だったので復習も兼ねて
migrateファイルに関してメモを残す。
migrationとは、SQLを使わずにスキーマ(DBのテーブルやカラムなどの構造)を変更できる手法。
Active Recordの機能の一つ。生のSQLを書かずにRubyの記法で書くことができる。
migrationファイルの作成方法は2種類。
# 1.モデル生成
bin/rails g model クラス名 or テーブル名
# model, migration, model spec, factoriesの4つのファイルを作成
# 2.migrateファイル生成
bin/rails g migration クラス名
# migrationファイルのみを生成
クラス名の後ろにfieldを追加することも可能。
クラス名は複数形にするのがデフォルトのよう。
migrationファイルを削除するときは必ずrollbackしてから
ちゃんとrollbackしてからでないと、NO FILEになってしまう。
マイグレーションが実行されたのにdb/migrate/ディレクトリ配下に存在しない場合に表示される。
NO FILEになった場合の対処は同じファイル名のmigrationファイルを作り直さないといけないので少し面倒。
db:migrate:resetとdb:resetの挙動の違い
どちらもDBを再生成した後にスキーマの定義までを実施するが、
前者はmigrateファイルを元にスキーマを定義する。後者はschema.rbを元に定義する。
さらに後者はseedデータも読み込む。
db:migrate:reset
- db:drop
- db:create
- db:migrate
db:reset
- db:drop
- db:create
- db:seed(?)
→実際に試した後、DBを見るとseedデータは読み込まれていなかった。(schema_migration, ar_internal_metadataというテーブルには登録されていた?)
私が今回試したプロダクトはなんらかの設定を施していて、db:reset実行時にseedを読み込まないようにしていたのかも。
schema_migration, ar_internal_metadata
resetした後に見つけたテーブル。migrateを実行すると自動的に生成されるテーブル。
schema_migrationは、migrationのタイムスタンプを保持するためのテーブルで、migrateするときは本ファイルを参照することで、変更分のみmigrateを行うことができる(と考えられる)。
例えば、以下のようなmigrationファイルがあったとすると、
20190701165640_create_articles.rb
schema_migrationには、以下のレコードが登録される。
20190701165640
これにより、migrate済みのファイルを管理できる。既にmigrateしているならmigrateを実行しない、ということが可能。
ar_internal_metadataは、自身のRails環境とスキーマに関する情報を保存するテーブル。
DBを意図せず削除されることを防止するためのテーブル。
このテーブルには、RAILS_ENVの情報を保持しており、environmentがproductionの場合はエラーとするために必要らしい。
防止の対象となるのは、下記を参考。drop以外はあまり使わなそう。
初期設定でオフにすることも可能。
add reference or add foreign key
別記事にまとめる。追加する制約が異なる。
互いの外部キーを持つテーブルのmigrateの書き方
互いに外部キーを持つリレーションの場合、先に定義するmigrateファイルは外部キー制約をつけることができない。存在しないテーブルの外部キーを持つことができないため。
この場合、両方のテーブルを定義した後に、外部キー制約を付与すれば良い。
具体な手法としては前述のadd reference等の方法があるが、迷いどころもある。
カラムを作っておいて外部キー制約だけを後付けするのか、カラムごと後で追加するか、というポイント。
文字数制限の定義方法
t.string name, limit: 20
t.integer huge_number, limit: 2.megabytes
stringなら文字数で、textやintegerはバイト数で定義する必要がある。
Active Record5.1からidカラムの型はデフォルトでbigintに変更された。
5.0以前はidカラムの型のデフォルトはintegerだったが、5.1からはbigintとなった。
外部キー制約を付与するときは、カラムの型が一致していなければならないため、
5.0以前なのか、5.1以降なのかをケアしてあげる必要がある。
Discussion