Edited at

Railsのマイグレーション管理方法について


まえがき

Railsのマイグレーション管理する方法についての個人的なめも。

賛否両論あると思いますが、まとめておきたいと思い、書いてます。

※誤記・不足あれば、ご支援いただけると助かります。


環境

Ruby 2.6.3

Rails 5.2.3

MySQL 5.7.25


状況

すでにモデルが一つ存在する状態での、カラム追加を想定しています。

◆Userモデル(Usersテーブル)

項目名
DBカラム名

補足

名前
name
String

mysql> desc users;

+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

◆Migrationファイル


db/migrate/20190813002037_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.2]

def change
create_table :users do |t|
t.string :name

t.timestamps
end
end
end


この状態の時、以下のカラムを追加したい場合。

項目名
DBカラム名

補足

年齢
age
Integer


方法1:マイグレーションファイルを追加していく方法(推奨)

メリット:既存データへの影響を少なくしてDB構成を変更出来ます。

 ※既にリリースしたサービスであれば、これが有効

デメリット:変更があるたびにマイグレーションファイルが追加されるため、ファイルが多くなり管理が難しくなります。

 ※現在のDB状態を見るには、DBを直接確認するか、db/schema.rbを確認しましょう。


rails g migrateを使って、追加します

rails g migration AddAgeToUser age:integer

コマンドひとつで、マイグレーションファイルが出来上がります。

※コマンドを実行した後に、作成されたファイルを修正するでも構いません。


db/migrate/20190813002439_add_age_to_user.rb

class AddAgeToUser < ActiveRecord::Migration[5.2]

def change
add_column :users, :age, :integer
end
end


rake db:migrateで、DBに反映します

$ rake db:migrate

== 20190813002439 AddAgeToUser: migrating =====================================
-- add_column(:users, :age, :integer)
-> 0.0376s
== 20190813002439 AddAgeToUser: migrated (0.0377s) ============================

ageが追加されました。

mysql> desc users;

+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)


方法2:既存マイグレーションファイルを修正する方法

メリット:マイグレーションファイルが1テーブル1ファイルになり、管理がし易くなります。

 ※このテーブルを修正したい場合はこのファイル!といった管理がし易くなります。

デメリット:反映時に既存データが消えるため、必要なデータについては、一旦退避するなどの対応が必要です。

 ※既にリリースしたサービスであれば、データ損失にもつながるので、推奨しません。


既存マイグレーションファイルを直接修正します


db/migrate/20190813002037_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.2]

def change
create_table :users do |t|
t.string :name
t.integer :age # ここを追加

t.timestamps
end
end
end



rake db:migrate:resetで、DBに反映します

$ rake db:migrate:reset

Dropped database 'migration_sample_development'
Dropped database 'migration_sample_test'
Created database 'migration_sample_development'
Created database 'migration_sample_test'
== 20190813002037 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0160s
== 20190813002037 CreateUsers: migrated (0.0161s) =============================

ageが追加された状態で再作成されます。

mysql> desc users;

+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

注意:

方法1と方法2では、ageの追加位置が違いますが、方法1でも追加位置を指定する事は可能です。


個人的な使い分け

最初のリリースまでは、方法2のパターンを使い、リリースした後からは方法1を使っています。

最初にきっちりDB構成を決めておけば、マイグレーションファイルの数を最小限に減らせると思いますが、

そんな簡単ではないですし、開発していくにつれ、「これもいる・これはいらない」というのがどうしても出てきてしまうと思います。

そのため、このような使い分けを私は使っています。