0
0

【ザックリ概要】`Active Record マイグレーション`について

Posted at

※一部ガイド内容を省略したりとザックリとしたまとめを意識しているので不十分な個所があるという点をご了承ください
(reference、外部キー関連、など省略)
*都度更新していく予定です


参考&引用サイト:Active Record マイグレーション


マイグレーションの概要

*"migration"(移行)⇒「DBのテーブル作成や変更」(「状態Aから状態Bへの"移行"」みたいな意味合いを持つ)

  • ActiveRecordの機能の1つ
  • DBスキーマ(テーブルの定義など)を長期にわたって安定して変更など加えられるようにする仕組み
  • 生のSQLを用いる必要が無い仕組みが大きな特徴と言える

  • マイグレーションの度に"マイグレーションファイル"が作成される。このファイルごとを"バージョン"と見なしている
  • schema.rbという「DBに管理してもらいたいテーブル定義書」の役割を持つファイルに対して変更内容が反映されていく
    • 直接schema.rbを触るのではなく、マイグレーションファイルに変更内容を記述して反映していく
      • これで変更のバージョン管理をしながらDBの最新状況の反映も行える

マイグレーションの例を以下に示します。

class CreateProducts < ActiveRecord::Migration[7.1]
  def change
    create_table :products do |t|
      t.string :name
      t.text :description

      t.timestamps
    end
  end
end
コード箇所 説明
create_table :products ~ "products"という名前のテーブルを作成
t.string :name String型のnameカラム
t.text :description text型のdescriptionカラム
t.timestamps created_atupdated_atの2つのカラムを追加(自動で生成&管理してくれる)
  • SQLを書かなくてもDBへのテーブル作成&カラム変更の命令を実装できる
  • 基本、マイグレーションファイルを編集してDBへ変更内容を反映する

マイグレーションを生成する

マイグレーションファイルについて

  • db/migrateディレクトリに保存
  • 1つのマイグレーションファイルが1つのマイグレーションクラスに対応(1対1)
    • 先述のマイグレーション例の場合、マイグレーションクラスCreateProductsに対してマイグレーションファイルYYYYMMDDHHMMSS_create_products.rbが対応する
  • マイグレーションファイル名はYYYYMMDDHHMMSS_create_products.rb(YYYYMMDDHHMMSS = "西暦 月 日 時 分 秒")
    • YYYYMMDDHHMMSS をファイル名につけることで「実行順番が必ず最新の反映内容が採用されるようになる」「一意になる」「変更履歴がファイル名から分かる」というメリットがある
$ bin/rails generate migration AddPartNumberToProducts

上を実行すると、空のマイグレーションが適切な名前で作成されます。

class AddPartNumberToProducts < ActiveRecord::Migration[7.1]
  def change
  end
end

新しいカラムを追加・削除する

  • マイグレーション時、コマンドに適切な引数を渡せば生成されるファイルに自動で中身に記述も加えてくれる

※"AddColumnToTable"、"RemoveColumnFromTable"をそのまま入力するのではなく以下のように書き換えるということ

コマンド マイグレーション内容
Add(追加したいカラム名)To(追加先テーブル) カラムの追加
Remove(削除したいカラム名)From(削除先テーブル) カラムの削除

マイグレーション名が"AddColumnToTable"や"RemoveColumnFromTable"で、かつその後ろにカラム名や型が続く形式になっていれば、適切なadd_column文やremove_column文を含むマイグレーションが作成されます。

$ bin/rails generate migration AddPartNumberToProducts part_number:string

上を実行すると以下のマイグレーションファイルが生成されます。

class AddPartNumberToProducts < ActiveRecord::Migration[7.1]
  def change
    add_column :products, :part_number, :string
  end
end

add_column :products, :part_number, :stringの部分は自動で追加した上でファイル生成してくれる

【構文】
$ bin/rails generate migration Add(カラム名)To(テーブル名) (カラム名1):(データ型1) (カラム名2):(データ型2) ... (カラム名N):(データ型N)
$ bin/rails generate migration Remove(カラム名)From(テーブル名) (カラム名1):(データ型1) (カラム名2):(データ型2) ... (カラム名N):(データ型N)

AddColumnToTableColumnに関しては任意の文字列でも問題ないという旨が確認される ← (未検証なので検証必要)
 (AddColumnToTableTableおよびRemoveColumnFromTableは不可) ← (これも未検証なので検証必要)

新しいテーブルを作成する

  • テーブルの作成はCreate(テーブル名)で指定する(要領はカラムの時と同じ)

$ bin/rails generate migration CreateProducts name:string part_number:string
上を実行すると以下のマイグレーションファイルが生成されます。

class CreateProducts < ActiveRecord::Migration[7.1]
  def change
    create_table :products do |t|
      t.string :name
      t.string :part_number

      t.timestamps
    end
  end
end

【構文】
$ bin/rails generate migration Add(カラム名)To(テーブル名) (カラム名1):(データ型1) (カラム名2):(データ型2) ... (カラム名N):(データ型N)

テーブル・カラムの変更

  • 既存のテーブルおよびカラムに対して変更も可能
    • ALTER TABLE...と同等の作用

#以下、ガイドより引用したテーブルの変更サンプル)

change_table :products do |t|
  t.remove :description, :name
  t.string :part_number
  t.index :part_number
  t.rename :upccode, :upc_code
end
詳細
t.remove :description, :name productsテーブルのdescription,nameカラムを削除
t.string :part_number productsテーブルにpart_numberを追加
t.index :part_number productsテーブルのpart_numberにインデックスを追加
t.rename :upccode, :upc_code productsテーブルのupccodeカラム名をupc_codeに変更

#以下、ガイドより引用したカラムの変更サンプル

change_column :products, :part_number, :text
詳細
change_column :products, :part_number, :text productsテーブルのpart_numberカラムのデータ型をtextに変更

マイグレーションの実行&ロールバック

  • 基本rails db:migrateでマイグレーションファイルの内容に従って実行される
    • まだ実行されていないdef changeを実行する。(本記事では省略したupメソッドも対象)
    • 未実行のマイグレーションがない場合は何もせずに終了
      • rails db:migrateを何回実行しても実害はないという事なので、「あれ?このマイグレーションファイルって実行したっけ?」という状況になったら確認の意味でも実行してするのもOK
    • マイグレーションの実行順序は、マイグレーションの日付が基準になります
      • これがマイグレーションファイル名をYYYYMMDDHHMMSS_create_products.rbとする理由
  • ロールバックは$ bin/rails db:rollback
    • マイグレーション実行はされていない。前の適用内容は取り消したよという状態
  • $ bin/rails db:migrate:redoのコマンドではロールバックしてからマイグレーション実行
    • $ bin/rails db:rollback && bin/rails db:migrateと同等

【構文】
rails db:migrate:最新のマイグレーションファイルの内容に従って実行
bin/rails db:rollback:最後に適用したマイグレーションファイルから1つロールバック(マイグレーションは未実行)

  • YYYYMMDDHHMMSSがバージョンの意味を持つので$ bin/rails db:migrate VERSION=YYYYMMDDHHMMSSと引数を渡すと「そのバージョンまでを実行する」といった指定実行を可能にしている
  • ロールバックも同様に「最新マイグレーション適用時点から何個前に遡るか」をSTEP=(バージョンダウンする数)で渡すことが可能。bin/rails db:rollback STEP=3とすると「最後に適用したマイグレーションから"3"つ前のマイグレーションにロールバックする」といった指令実行になる

*なんとなく「ファイル名に作成時刻を入れてる」な程度の認識でいたが、"YYYYMMDDHHMMSS"はバージョンとしての意味合いが強い点は留意すべき

スキーマダンプの意義

*「schema.rbというファイルは必要あるの?」という章
>基本schema.rbを直接触らないのに何でファイルとして置いておくのか

  • 「DBのマイグレーション適用状況がschema.rbから分かる」から
    • より砕くと「何か色々とマイグレーションファイルを作って実行してきたが、現状はどんな感じでスキーマが構築されているんだろう?」という時にマイグレーションファイルを1つ1つログのように辿るのではなく、スキーマファイルを確認して最終的なマイグレーションの反映状況を把握するのに役立つ
  • 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