Ruby on Railsでのマイグレーションをわかりやすく解説

はじめに

皆さんはRuby on RailsのMigrationという仕組みを聞いたことがあるでしょうか。

Railsでデータベースのテーブルを作成したり、テーブルにカラムを追加したりする際に使われる機能で、プロジェクトの進捗に合わせてデータベースの構造を柔軟に変化させることができます。

ただ、プログラミング未経験の方や学習を始めたばかりの方にとっては「なぜMigrationが必要なのだろう」と疑問になるかもしれません。

そこで、本記事ではMigrationの基本や使い方を具体的に解説します。

また、どのようなケースで役に立つかなど実務での活用もイメージできるようにしていきます。

初心者の方でも読めばスッと理解できるよう、専門用語をなるべくかみ砕いてお伝えします。

この記事を読むとわかること

  • Ruby on RailsのMigrationとは何か
  • データベースのスキーマ変更を安全に行う方法
  • Migrationファイルの作成方法と実行方法
  • 実務で活用する際のポイント
  • よくあるエラーやつまずきポイントと対処法

最初に、Migrationを使うとどのようなメリットがあるのかを整理しながら学んでみましょう。

Migrationを使うメリット

Migrationを導入すると、チーム開発でデータベース構造を共有したり、更新したりするのが楽になります。

また、一度作ったテーブルを後から微調整する際にも履歴がわかりやすくなるため、複数人で同じプロジェクトを進めるときにはとても便利です。

一方で、使い方を誤るとエラーが出てしまいがちなので、基本ルールをしっかり把握しておく必要があります。

Migrationとは何か

Railsでは、データベースのスキーマ(構造)をバージョン管理する仕組みとしてMigrationが存在します。

プログラムのコードと同じように、データベースの変更内容をファイルで管理するというわけです。

たとえば、新しいテーブルを作ったり、カラムを追加・変更・削除したりする際にMigrationファイルを作成して、そのファイルを実行(migrate)することで、実際のデータベース構造に反映させます。

ここで少し気をつけておきたいのは、Migrationファイルの順番が開発の履歴になっている点です。

複数のファイルを通じて「どのタイミングで何を変更したか」が明確になります。

初心者の方でも無理なく覚えられるよう、さらに詳しく解説していきましょう。

実務でよくあるシーン

  • 新機能を実装するためにテーブルやカラムを追加する
  • 不要になったカラムを削除する
  • データ型を変更して扱いやすくする
  • 複数人で同じデータベースをいじる際、変更履歴を共有する

これらはいずれもよくあるケースです。

もしMigrationを使わずに手作業でSQLを発行して変更していたら、誰かが修正を忘れたり重複して作業したりして混乱を招くかもしれません。

Migrationを習得しておくと、そうしたリスクを抑えつつ安全にスキーマ変更ができるでしょう。

Migrationファイルの基本構造

RailsでMigrationファイルを作ると、Rubyファイルとして下記のような形が生成されます。

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.integer :age
      t.timestamps
    end
  end
end

create_tableというメソッドを使って、usersというテーブルを定義している例です。

t.string :nameのように書くことで、nameというカラム(文字列型)を作成していることがわかります。

さらにt.integer :ageは年齢を管理するためのカラムです。

最後にt.timestampsを入れておくと、自動的に「created_at」「updated_at」という2つのカラムが追加されます。

このファイルをRailsのコマンドで実行すると、実際のデータベースにusersテーブルが作成されます。

add_columnやrename_columnなど

RailsのMigrationには、他にもさまざまなメソッドが用意されています。

下記はよく使われるものです。

メソッド名用途
add_column既存テーブルに新しいカラムを追加するときに使う
remove_column既存テーブルからカラムを削除するときに使う
rename_column既存テーブルのカラム名を変更するときに使う
change_column既存カラムのデータ型やデフォルト値を変更するときに使う
create_table新しいテーブルを作成するときに使う
drop_table既存テーブルを削除するときに使う
add_index検索やレコード取得の高速化を狙うためにインデックスを追加するときに使う
remove_index既存のインデックスを削除するときに使う

たとえば既存のusersテーブルに「email」という文字列カラムを追加したい場合は、以下のように書きます。

class AddEmailToUsers < ActiveRecord::Migration
  def change
    add_column :users, :email, :string
  end
end

こうしてMigrationファイルを作成して、Railsのコマンドを実行すれば変更が反映されます。

Migrationの実行とロールバック

Migrationファイルを作成したら、実行コマンドを用いてデータベースに変更を加えます。

多くの場合は以下のようなコマンドを使います。

rails db:migrate

このコマンドを実行すると、未実行のMigrationファイルが順番に処理され、データベース構造が更新されます。

もし何か間違いがあった場合や、元に戻したい場合は「ロールバック」という仕組みが役に立ちます。

rails db:rollback

このコマンドを実行すると、最後に行ったMigrationが取り消されます。

もし複数回分戻したい場合は、STEPオプションを付けて以下のように実行します。

rails db:rollback STEP=2

これで直近2回分の変更が取り消されるというわけです。

ロールバックができる点は、チーム開発の際やリリース直後に不具合が見つかったときにも便利でしょう。

実務で気をつけたいポイント

例えば、既に大量のデータが入っているテーブルのカラムを削除する場合などは、一度削除してしまうと元に戻すのが難しくなることがあります。

ロールバック機能を使えば定義上は元に戻せるはずですが、データそのものを復元するのは容易ではありません。

そういった点にも注意しつつ、Migrationを運用する必要があります。

Migrationファイルを作成するコマンド

RailsにはMigrationファイルを自動生成するコマンドがいくつか用意されています。

たとえば、新規テーブルを作るために「create_users」というMigrationファイルを作る場合は、次のように実行します。

rails generate migration CreateUsers

あるいは「emailカラムをusersテーブルに追加する」というMigrationファイルを作るなら、

rails generate migration AddEmailToUsers email:string

のように書くことができます。

ファイル名の指定や、どのカラムが欲しいかを記述することで、自動的に骨組みのコードが生成されるのは大変便利です。

生成されたファイルを少し手直しして、あとはrails db:migrateで適用します。

generateコマンドの活用例

チームメンバーが別のテーブルを作るためにMigrationを生成しているとき、自分も似たような作業を始める場合があります。

この際、コマンドでファイル名やカラムを指定すれば、ミスを減らしやすいでしょう。

ファイル名を人間が読みやすいようにしておくと、後からどのファイルが何をしているか把握しやすくなります。

実務で活用するための流れ

実際に現場でMigrationを使う場合の流れをもう少し見てみましょう。

1. まず仕様変更や新機能の要件が決まる

たとえば「ユーザーが電話番号を登録できるようにしたい」という要件が出たとします。

2. Migrationファイルを作成

先ほどのgenerateコマンドなどを使って、AddPhoneNumberToUsersのような名前でファイルを用意します。

3. コード内容を編集

add_column :users, :phone_number, :string のように、必要なカラムを追加するためのコードを書きます。

4. コマンドでmigrate

rails db:migrateで変更を反映します。 実際にデータベースのスキーマが変わったか、Railsコンソールやアプリケーションの画面で確認するのも大切です。

5. エラーが出たり仕様変更があった場合、修正して再びmigrate

問題があればロールバックなどを行いながら、調整を続けます。

このような手順でRailsのコードもデータベースも一緒に進化させていきます。

Migrationでよくあるエラーと対処法

初心者の方が最初によく遭遇するエラーとしては、以下のような例があります。

  • 実行順序の問題で想定外のテーブルが存在しない
  • rename_columnやremove_columnで対象のカラム名を間違える
  • データ型を変更した際、既存のデータが不正になってしまう

特に注意が必要なのは、誤ったカラム名を指定しているケースです。

rename_column :users, :mail, :email というように書きたいのに、カラム名を打ち間違えてしまうとエラーが出るか、意図した変更にならない場合があります。

ロールバックをうまく使いこなしながら何度かやり直せば解決できますが、大切なデータを扱うプロジェクトではテスト環境で試してみるなど慎重に進めると安心です。

一度削除したカラムに入っていたデータを復元することは難しい場合があります。 誤って消してしまったときは、バックアップから復元できるようにしておくとリスクが下がるでしょう。

実務で役立つ応用的な使い方

Migrationはテーブルやカラムの変更以外にも、ちょっとしたバッチ処理を行うための記述を含めることがあります。

たとえば、既存のレコードに対してデータの変換を実行するようなスクリプトを記述しておくことも可能です。

しかし、あまり複雑なロジックをMigrationファイルに詰め込むと、今度はロールバックしたいときに扱いが難しくなることもあります。

実務では「データの移行」というステップと「スキーマの変更」というステップを分割するなど、工夫がよく行われています。

changeメソッドとup/downメソッド

RailsのMigrationでは、基本的にchangeメソッドを使ってテーブルの作成や変更を記述します。

ただし、changeメソッドで書くとロールバックの挙動が明確に定義できない場合があります。

たとえば、単純にテーブルを作るだけなら良いのですが、複雑な処理を含むと自動では戻せない可能性があるのです。

そういうときは、upメソッド(migrate時の動作)とdownメソッド(rollback時の動作)の2つを使って明示的に記述するとよいでしょう。

class AddStatusToTasks < ActiveRecord::Migration
  def up
    add_column :tasks, :status, :string, default: "open"
  end

  def down
    remove_column :tasks, :status
  end
end

こうしておけば、Railsがロールバックすべきときにdownメソッドを実行してくれます。

チーム開発でのMigration運用

チーム開発では、複数人が同時にMigrationファイルを作成する機会があります。

その場合、以下のポイントを意識しておくと混乱を避けられます。

ファイル名をわかりやすく

何をするファイルなのか、一目でわかる名前をつけると後から見返しやすいです。

Migrationファイルの順序管理

Railsではタイムスタンプをベースに管理しているため、同じタイミングで複数のMigrationファイルを作るとコンフリクトしそうに見えますが、実行順序はファイル名の数字で決まります。

pull/pushのタイミング

Gitなどのバージョン管理を利用している場合は、Migrationファイルを作る前に最新のコードをpullしておくことが大切です。 そうしないと、他の人が作ったMigrationファイルとの整合性が取れなくなる可能性があります。

チーム開発では常にMigrationが衝突する可能性があります。 こまめにコミュニケーションを取ることで、衝突を防ぎやすくなるでしょう。

よくある質問や勘違い

初心者の方からよく出る疑問をいくつか紹介します。

Q. Migrationファイルは全部残しておく必要がある? A. はい。基本的には残しておきます。ファイルそのものが更新履歴としての役割を果たすからです。 プロジェクトが大規模になりすぎたときに、ある程度まとめる作業をすることはありますが、初心者のうちは気にしなくても問題ありません。

Q. テーブルの作成と削除を一度に行うのはどうする? A. 同じMigrationファイル内で複数の処理を書けば可能ですが、可読性を考えると用途ごとにファイルを分けることが多いです。

Q. rails db:migrateを実行してもテーブルができない A. マイグレーションファイルにスペルミスがある、あるいは既に同じテーブルを作る別のMigrationが走っているなどが考えられます。ターミナルのエラーメッセージをよく読んで対処しましょう。

実務におけるマイグレーション設計のポイント

マイグレーションは、コードと同様に未来に渡って維持・管理する必要がある大切な要素です。

以下の点を意識して設計すると、後々トラブルが起きにくくなります。

できるだけ小さな粒度で変更を行う

一度にたくさんのテーブルやカラムを変更すると、どこでエラーが起こったのか把握しづらくなります。

意味のあるファイル名とクラス名をつける

たとえば「AddPhoneToUsers」など、何をするファイルか一目瞭然になります。

テスト環境で試してから本番反映する

変更内容が大きい場合は、ローカルやステージング環境などで試し、本番環境に適用する前に問題がないか確認しておくと安心です。

ロールバックも念頭において書く

もしもコードで意図しない不具合が起きた場合に備え、downメソッドをしっかり定義しておくと安全です。

マルチデータベースやマルチテナントでの注意点

少し上級者向けの話ですが、Railsでは複数のデータベースを扱うケースもあります。

その場合、Migrationの書き方や実行方法が通常と異なる場合があるので注意してください。

また、サービスによっては複数の顧客(テナント)のデータをそれぞれ別のスキーマで管理することもあります。

このような設計では、Migrationをどのスキーマに適用するのかを明確に定義しておかないと、思わぬトラブルが発生することがあります。

初心者の方が最初からこうした応用を扱う機会は少ないと思いますが、機能があることだけ知っておくと安心ですね。

まとめ

ここまで、Ruby on RailsのMigrationについて初心者の方にもわかりやすいように解説してきました。

Migrationは、データベースの構造を安全に変更し、その履歴を残しやすくするための仕組みです。

初心者のうちはテーブルの作成やカラムの追加など、シンプルなところから慣れていくと良いでしょう。

そして、チーム開発で複数人が同時に作業するような場面では、Migrationファイルの命名や衝突を防ぐルールの整備が鍵になります。

コードと同じようにデータベースの変更も管理できるようになると、開発効率も保守性も高められます。

一歩ずつ学習を進めていけば、これから大規模なアプリケーションを作るときにも大きな武器になるでしょう。

Rubyをマスターしよう

この記事で学んだRubyの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。