LoginSignup
83
81

More than 5 years have passed since last update.

RailsのMigrationに関する基本まとめ

Last updated at Posted at 2018-12-19

Rails初心者でmigration操作について悩む人(自分)のための忘備録

とりあえず基本の確認

データベースを変更するときの大まかな流れは以下。

1.$ rails g migrationコマンドでマイグレーションファイルを作成
2.マイグレーションファイルの中身を書き換える
3.$ rails db:migrateコマンドでマイグレーションを順番に実行してデータベースに変更を加える

今回サンプルとして以下のようなデータ構造を持つUserテーブルを作成する↓

カラム名 データ型
id integer
name string
profile text
created_at datetime
updated_at datetime

1. 空のマイグレーションファイルを作成する

とりあえずrails g migrationコマンドを打ってみる↓

# 空のmigrationファイルを作成する
$ rails g migration create_user 
Running via Spring preloader in process 2198
      invoke  active_record
      create    db/migrate/20181219035049_create_user.rb # 20181219035049というのがmigrationファイルが作られた日時

# マイグレーションの実行状況を確かめる
$ rails db:migrate:status

database: hogehoge/your_project

 Status   Migration ID    Migration Name
--------------------------------------------------
 down     20181219035049  CreateUser # statusが'down'となっているのはマイグレーションがまだ実行されていないことを示している

db/migrate配下に、現在時刻を記録したmigrationファイルが作成された↓

# db/migrate/20181219035049_create_user.rbの中身
class CreateUser < ActiveRecord::Migration[5.2]
  def change
  end
end

2. データベースに変更を加える

当たり前だがマイグレーションファイルを作成しただけでは、データベースは変更されない。

先ほど作成したマイグレーションファイルの中身を書き換えて、rails db:migrateを打てば完了。
rails db:migrateによってchangeメソッドとupメソッドが順番に実行される。

# db/migrate/20181219035049_create_user.rbを書き換える
class CreateUser < ActiveRecord::Migration[5.2]
  def change # rails db:migrateで実行されるメソッド
    create_table :users do |t| #usersという名前のテーブルを新たに作成
      #(idカラムは自動で割り当てられる)
      t.string :name #string型のnameカラムを作成
      t.text :profile #text型のprofileカラムを作成
      t.timestamps #created_at, updated_atを自動で作成
    end
  end
end
#マイグレーションファイルを実行してデータベースに変更を加える
$ rails db:migrate
== 20181219035118 CreateUsers: migrating ======================================
-- create_table(:user)
   -> 0.0024s
== 20181219035118 CreateUsers: migrated (0.0026s) =============================

# マイグレーションの実行状況を確かめる
$ rails db:migrate:status

database: hogehoge/your_project

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20181219035049  CreateUser # statusが'up'に変わり、マイグレーションが正常に実行されたことを示している

3. データベースへの変更を取り消す

rails db:rollbackコマンドによって、直前の変更(migrationファイル1つ分)を取り消すことができる。
rails db:rollbackによってchangeメソッドに定義された処理が逆順に実行される。
downメソッドがあればそれも順番に実行していく。

# 直前のマイグレーションの取り消し
$ rails db:rollback
== 20181219036118 CreateUsers: reverting ======================================
-- drop_table(:users) #usersテーブルを削除
   -> 0.0014s
== 20181219036118 CreateUsers: reverted (0.0034s) =============================

# マイグレーションの実行状況を確認
$ rails db:migrate:status

database: hogehoge/your_project

 Status   Migration ID    Migration Name
--------------------------------------------------
 down     20181219035049  CreateUser

この状況でマイグレーションファイルを削除すれば変更完了。

change_columnはロールバックできない

Migrationファイル

class ChangeColumnToUser < ActiveRecord::Migration[5.2]
  def change
    change_column :users, :name, :text
  end
end
terminal
# db:migrateは実行できる
$ rails db:migrate
== 20181219044049 ChangeColumnToUser: migrating =======================
-- change_column(:users, :name, :text)
   -> 0.1817s
== 20181219044049 ChangeColumnToUser: migrated (0.1819s) ==============

# db:rollbackはできない
$ rails db:rollback
== 20181219045049 ChangeColumnToUser: reverting ============================
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

ActiveRecord::IrreversibleMigration # マイグレーションが可逆でないことを示すエラー

changeメソッドの中でchange_columnを使おうとすると、マイグレーションが可逆的でないというエラーが発生する。
これはchangeメソッドが行える処理の中に、change_columnが定義されていないからである。
公式ドキュメントによるとchangeメソッドは以下の処理しか実行できない↓

現時点では、changeでサポートされているマイグレーション定義は以下のものだけです。

add_column
add_foreign_key
add_index
add_reference
add_timestamps
change_column_default (:fromと:toの指定は省略できない)
change_column_null
create_join_table
create_table
disable_extension
drop_join_table
drop_table (ブロックを渡さなければならない)
enable_extension
remove_column(型を指定しなければならない)
remove_foreign_key(2番目のテーブルを指定しなければならない)
remove_index
remove_reference
remove_timestamps
rename_column
rename_index
rename_table

--- Rails公式ドキュメントより引用 ---

change_columnを使いたい場合、up,downメソッドを定義してあげると良い。

migration
class ChangeColumnToUser< ActiveRecord::Migration

  # 変更内容(db:migrate時に実行される)
  def up
    change_column :users, :name, :string #nameカラムのデータ型をstringへ変更
  end

  # 変更前の状態(db:rollback時に実行される)
  def down
    change_column :users, :name, :text
  end
end

このようにすると変更前と変更後の状況がはっきりするため、ロールバックが可能になる。

使えそうなメソッド

migration.rb
# 指定したテーブルに関して色々な操作を一括でできる'change_tableメソッド'
change_table :products do |t|
  t.remove :description, :name #description,nameカラムを削除
  t.string :part_number #part_numberカラムを追加
  t.index :part_number
  t.rename :upccode, :upc_code #upccodeカラムをupc_codeへ変更
end


# カラムの順番を特定の位置にしたいとき
class AddColumn3ToUsers < ActiveRecord::Migration
  def change
    add_column :users, :column3, :string, after: :column2 #afterに指定したカラムのすぐ後にカラムを追加する
  end
end

※訂正点などあればご指摘いただけると幸いです。

参考にした記事

Active Record マイグレーション | Rails ガイド
rails generate migrationコマンドまとめ | Qiita

83
81
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
83
81