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
はロールバックできない
class ChangeColumnToUser < ActiveRecord::Migration[5.2]
def change
change_column :users, :name, :text
end
end
# 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
メソッドを定義してあげると良い。
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
このようにすると変更前と変更後の状況がはっきりするため、ロールバックが可能になる。
使えそうなメソッド
# 指定したテーブルに関して色々な操作を一括でできる'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