はじめに
毎回ググってる気がするので、まとめました。
右側の目次からお探しの用語やコマンドをクリックしてお使いください!
対象となる読者
- マイグレーションに苦手意識のある初心者の方
- 復習も兼ねて基本操作を中心におさらいしたい経験者の方
- マイグレーション関連でハマりたくない方
###テーブルを作る
modelを作成すると/db/migrate/ 以下にマイグレーションファイルも一緒に作成されます。
この場合クラス名はUser
、name
,email
という属性にデータタイプ(型)としてstring
を指定しています。
$ rails g model User name:string email:string
invoke active_record
create db/migrate/20200130031151_create_users.rb ← マイグレーションファイル
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
マイグレーションファイルには先ほど指定したクラス、changeメソッドの中にテーブル名(指定したモデルの複数形になります)、属性(カラム)、データタイプ(型)などが記載されており、db:migrateコマンドで適用させると、この設計図でテーブルが作成されます。
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
データタイプ(型)の種類
-
string
: 文字列 -
text
: 長い文字列 -
integer
: 整数 -
float
: 浮動小数 -
decimal
: 精度の高い小数 -
datetime
: 日時 -
timestamp
: タイムスタンプ -
time
: 時間 -
date
: 日付 -
binary
: バイナリデータ -
boolean
: Boolean
※rails generate migrationコマンドまとめ @zaru
カラム修飾子(オプション)
-
limit
: string/text/binary/integerフィールドの最大サイズを設定します。 -
precision
: decimalフィールドの精度 (precision) を定義します。この精度は、その数字の総桁数で表されます。 -
scale
: decimalフィールドの精度 (スケール: scale) を指定します。この精度は小数点以下の桁数で表されます。 -
polymorphic
: belongs_to関連付けで使うtypeカラムを追加します。 -
null
: カラムでNULL値を許可または禁止します。 -
default
: カラムでのデフォルト値の設定を許可します。dateなどの動的な値を使う場合は、デフォルト値は最初 (マイグレーションが実行された日付など) にしか計算されないことに注意してください。 -
index
: カラムにインデックスを追加します。 -
comment
: カラムにコメントを追加します。
ちなみにnull
とdefault
はコマンドラインで指定できません。
データタイプ(型)、カラム修飾子(オプション)を指定してテーブルを作る
$ rails g model Product name:string:index sku:string{10}:uniq \
supplier:references{polymorphic} 'price:decimal{10,2}'
index
は追加したいカラムに記述するだけです。
limit
やpolymorphic
は{}内に記述。
precision
、scale
はカラムとdecimal型、引数{precisionの値,scaleの値}を``で括ると適用されました。
20200131044330_create_products.rb
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :name
t.string :sku, limit: 10
t.references :supplier, polymorphic: true
t.decimal :price, precision: 10, scale: 2
t.timestamps
end
add_index :products, :name
add_index :products, :sku, unique: true
end
end
db:migrateで適用させるとテーブルが作成されます。
schema.rb
create_table "products", force: :cascade do |t|
t.string "name"
t.string "sku", limit: 10
t.string "supplier_type"
t.bigint "supplier_id"
t.decimal "price", precision: 10, scale: 2
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["name"], name: "index_products_on_name"
t.index ["sku"], name: "index_products_on_sku", unique: true
t.index ["supplier_type", "supplier_id"], name: "index_products_on_supplier_type_and_supplier_id"
end
普通にマイグレーションファイルを作成し、後でオプション記述する方が早くて確実な気もしますが、お好みでどうぞ。
テーブルを削除する
usersテーブルを削除します。
$ rails g migration DropUsers → マイグレーションファイルを削除する場合
$ rails destroy model User → モデルを削除する場合(マイグレーションファイルを含む、rails g model Userで作成されたファイル全てを削除。)
今回はマイグレーションファイルのみ削除したいので、$ rails g migration DropUsers
を実行します。
実行すると空のChangeメソッドが生成されます。
ここにdrop_table :テーブル名
と書いてdb:migrateコマンドで適用させると削除できます。
ただこれだとrollbackが効きません。(元に戻せない)
class DropUsers < ActiveRecord::Migration
def change
drop_table :users
end
end
rollbackさせるには
- changeメソッドでrollbackを効かせるためにブロックを渡す。
- upメソッド、downメソッドを使う。
class DropUsers < ActiveRecord::Migration
def change
drop_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
class DropUsers < ActiveRecord::Migration
def up
drop_table :users
end
def down
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
これであればrails db:migrate
で削除、やっぱり戻したいとなってもrails db:rollback
でrollbackできますので安心して削除できます。
db:migrateやdb:rollback、changeメソッドのrollbackについてはマイグレーションあれこれで詳しく解説しております。
###テーブル名を変更する
$ rails g migration RenameProducts
実行すると空のチェンジメソッドが生成されますので、
中にrename_table :既存のテーブル名, :変更後のテーブル名
を記載しdb:migrateコマンドで適用させるとテーブル名が変更されます。
class RenameProducts < ActiveRecord::Migration
def change
rename_table :products, :goods
end
end
###カラムを追加する、オプションを追加する。
usersテーブルにadmin
カラム、データタイプ(型)はboolean
を指定し、追加してみます。その後生成されたマイグレーションファイルにdefault: false
オプションを記述します。
$ rails g migration (AddAdminToUsersもしくはadd_admin_to_users) admin:boolean
生成されたマイグレーションファイルにdefault: false
を記述すれば、db:migrateで適用できます。
20200131051723_add_boolean_to_users.rb
class AddAdminToUsers < ActiveRecord::Migration
def change
add_column :users, :admin, :boolean, default: false
end
既存のカラムに変更を加える
usersテーブルにprofile:string
というカラムがあったとします。それをprofile:text
に変更します。
$ rails g migration (ChangeProfileDatatypeOfUsersもしくはchange_profile_datatype_of_users)
空のchangeメソッドが生成されますが、rollbackを効かせるために、up,downメソッドを使用します。db:migrateで変更が適用されます。
class ChangeProfileDatatypeOfUsers< ActiveRecord::Migration
# 変更内容
def up
change_column :users, :profile, :text
end
# 変更前の状態
def down
change_column :users, :profile, :string
end
end
###カラムを削除する
usersテーブルのprofile:text
というカラム削除します。
$ rails g migration (RemoveProfileFromUsersもしくはremove_profile_from_users) profile:text
実行すると空のchangeメソッドが生成されています。
ここにremove_column :テーブル名, カラム名
と書いてdb:migrateコマンドで適用させると削除できます。
ただこれだとrollbackが効きません。(元に戻せない)
class RemoveProfileFromUsers < ActiveRecord::Migration
def change
remove_column :users, :profile
end
end
rollbackさせるには
- changeメソッドでrollbackを効かせるためにオプション(型)を指定する。
- 従来のupメソッド、downメソッドを使う。
rails db:migrateで変更を適用できます。
class RemoveProfileFromUsers < ActiveRecord::Migration
def change
remove_column :users, :profile, :text
end
end
class RemoveProfileFromUsers < ActiveRecord::Migration
# 変更内容
def up
remove_column :users, :profile, :text
end
# 変更前の内容
def down
add_column :users, :profile, :text
end
end
これであればrails db:migrate
で削除、やっぱり戻したいとなってもrails db:rollback
でrollbackできますので安心して削除できます。
db:migrateやdb:rollback、changeメソッドのrollbackについてはマイグレーションあれこれで詳しく解説しております。
###カラム名を変更する
postsテーブルのimage
カラムをpicture
カラムに変更してみます。
$ rails g migration (RenameImageToUsersもしくはrename_image_to_users)
change
メソッドが生成されます。rollbackを効かしたい場合は、up,down
メソッドで書きましょう。db:migrateで変更を適用できます。
class RenameImageToUsers < ActiveRecord::Migration
# 変更内容
def up
rename_column :users, :image, :picture
end
# 変更前の内容
def down
rename_column :users, :picture, :image
end
end
マイグレーションファイルの名前の付け方
カラムを追加、削除、変更する場合、AddColumnToUsers
やChangeColumnOfUsers
、
RemovColumnFromUsers
といった名前をつけてしまうと、同テーブルのカラムを追加、変更、削除したくなった時に名前が被る可能性があるので、
-
AddAdminToUsers
(usersテーブルにadminカラムを追加する) -
ChangeProfileDatatypeOfUsers
(usersテーブルのプロフィールカラムのデータタイプを変更する) -
RemoveProfileFromUsers
(usersテーブルからプロフィールからむを削除する)
といった具合に、より具体的な名前をつける方が良さそうです。
マイグレーションあれこれ
db:migrate
rails db:migrateを実行すると、基本的にこれまで実行されたことのないchangeまたはupメソッドを実行します。未実行のマイグレーションがない場合は何もせずに終了します。マイグレーションの実行順序は、マイグレーションの日付に基づきます。db/schema.rbスキーマファイルを更新し、スキーマがデータベースの構造に一致するようにします。
db:rollback
rails db:rollbackで直前に行ったマイグレーションをロールバックします。
これによりchangeメソッドを逆転実行するかdownメソッドを実行します。
db:rollback STEP=()
$ rails db:rollback STEP=2
これにより、最後に行った2つのマイグレーションがロールバックされます。
rails db:migrate:statusで状況を確認してコマンド実行しましょう。
db:migrate:status
rails db:migrate:statusを実行するとStatus
のup,down(マイグレーションが適用されているかどうか)とID
、マイグレーションファイル名
が閲覧できます。
Status Migration ID Migration Name
--------------------------------------------------
up 20200131044330 Create products
up 20200131051621 Create users
up 20200131051723 Add boolean to users
down 20200131054638 Add profile to users
db:migrate VERSION=()
$ rails db:migrate VERSION=20200131062759
マイグレーションの特定のバージョンを指定すると、Active Recordは指定されたマイグレーションに達するまでマイグレーション (change/up/down) を実行します。VERSIONはdb:migrate:statusコマンドで確認できます。
db:migrate:redo
db:migrate:redoコマンドは、ロールバックと再マイグレーションを一度に実行できるショートカットです。複数バージョンに対してこれを行いたい場合は、db:rollbackコマンドの場合と同様にSTEPパラメータを指定することもできます。
ロールバック Railsガイド
普段db:migrateする際は、はじめからrails db:migrate:redo
を実行し、rollbackの動きをを担保しておくといいかもしれません。
changeメソッド、up,downメソッド
changeメソッドはいい感じにrollbackを行ってくれて便利なんですが、サポートされているマイグレーション定義を把握してから使用しないと、二度手間になりかねません。
(drop_tableはブロックを渡さなければならない、remove_columnは型を指定しなければならないなど)
無駄なマイグレーションファイルを作成しなくて済むように、使用する場合はサポートされているマイグレーション定義を確認しておきましょう。
changeメソッドは、マイグレーションを自作する場合に最もよく使われます。このメソッドを使えば、Active Recordがマイグレーションを逆方向に実行 (ロールバック) する方法を自動的に理解してくれるため、多くの場面で利用できます。
[changeメソッドを使う Railsガイド]
(https://railsguides.jp/active_record_migrations.html#change%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%92%E4%BD%BF%E3%81%86)
面倒な場合は確実なupメソッド、downメソッドを使用してもいいと思います。現場に合わせて適時使い分けていただければと思います。
おわりに
もしこの記事が為になった!という方はフォローやいいねボタンのクリックをしていただけたらとても嬉しいです!
参考
Railsガイド
rails generate migrationコマンドまとめ @zaru
Ruby on Railsでテーブルのカラムを追加・削除する方法 @Reasonable Code