Help us understand the problem. What is going on with this article?

rails generate migrationコマンドまとめ

More than 1 year has passed since last update.

RailsでDBスキーマ周りをいじろうとすると、たいていrails generate migrationコマンドあたりがでてくるんだけど、なんかいまいちどういう使い方ができるのか、分からなかったのでまとめてみる。

基本コマンド

command
# マイグレーションファイル作成コマンド
$ rails generate migration クラス名

# モデル作成
$ rails generate model モデル名

クラス名は何でもOKだけど「アクション+テーブル名」とかが慣例っぽいです。分かりやすければ良いかな。これで /db/migrate/タイムスタンプ_クラス名.rb というファイルが作れる。ここに、スキーマの変更点を記載すればOK。

モデルの新規作成はmodel モデル名。命名規則はモデル名とテーブル名の規約を参照。

generateは g と略すことができるので、ぜひ略そう。

テーブルを作る

command
$ rails g model モデル名 フィールド:型:(unique|index) 以降必要なだけ

こんな感じのusersテーブルを作成したい場合

command
mysql> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| uuid       | varchar(255) | YES  |     | NULL    |                |
| name       | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime     | YES  |     | NULL    |                |
| updated_at | datetime     | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
command
$ rails g model User uuid:string:unique name:string

こうすればOK。サロゲートキー(id)とレコードの作成日時/更新日時のタイムスタンプは自動で作られる。これ、NOT NULLはどうやって指定するんだろ…。

/db/migrate/ 以下にマイグレーションファイルが作成されるので、NOT NULLだったり、カラム名の修正とかをしたい場合は、ここで直接修正してしまう。

指定できる型

  • string : 文字列
  • text : 長い文字列
  • integer : 整数
  • float : 浮動小数
  • decimal : 精度の高い小数
  • datetime : 日時
  • timestamp : タイムスタンプ
  • time : 時間
  • date : 日付
  • binary : バイナリデータ
  • boolean : Boolean

マイグレーション実行&ロールバック&確認

このままだと、実際のDBには反映されないので、db:migrateコマンドを実行する。

command
# 実行
$ rake db:migrate
command
# ロールバック
$ rake db:rollback
command
# 確認
$ rake db:migrate:status

database: hoge_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20140909055128  Create users
   up     20140909055234  Create spots
   up     20140909055735  Create user spots
   up     20140909072813  Change options to user spot

テーブルを削除する。

command
$ rails g migration DropUser
class DropUser < ActiveRecord::Migration[5.0]
  def change
    drop_table :users
  end
end

ロールバックを効かせるため、以下のように up と down を明示しておくとよいと思います。

class DropUser < ActiveRecord::Migration[5.0]
  def up
    drop_table :users
  end
  def down
    create_table :users do |t|
      t.string :uuid
      t.string :name
      t.timestamps
    end
  end
end

テーブル名を変更する

すでに存在しているテーブルの名前を変更したくなった場合。

command
$ rails g migration RenameIssueToTask
/db/migrate/20140909095843_rename_issue_to_task.rb
class RenameIssueToTask < ActiveRecord::Migration
  def change
    rename_table :issues, :tasks
  end
end

既存カラムを変更する

すでに存在しているテーブルのカラムを変更したくなった場合。

command
$ rails g migration ChangeColumnToUser
/db/migrate/20140909095843_change_column_to_user.rb
class ChangeColumnToUser< ActiveRecord::Migration

  # 変更内容
  def up
    change_column :users, :uuid, :string, null: false, default: 0
  end

  # 変更前の状態
  def down
    change_column :users, :uuid, :string, null: true, default: 0
  end
end

この例は、UserモデルのuuidカラムをNOT NULL制約に変更した。updownのメソッドによって、マイグレーションの適用前と適用後を明示的にできる。つまり、ロールバックすることができる。

どっかで、migration クラス名のクラス名部分に命名規則があって、それに従うと便利っぽいことが書かれていたんだけど、よく分からんので、普通に見て分かる名前でいいと思う。

オプション

NULL / NOT NULL

/db/migrate/example.rb
# NULL
change_column :テーブル名, :カラム名, :, null: true

# NOT NULL
change_column :テーブル名, :カラム名, :, null: false

インデックス

/db/migrate/example.rb
change_column :テーブル名, :カラム名, :, index: true

デフォルト

/db/migrate/example.rb
change_column :テーブル名, :カラム名, :, default: "piyo"

すでに設定してあるデフォルト値を消す場合は change_column_default を利用する。さらに false を指定してしまいがちだが、 nil にしないと Integer の場合は DEFAULT 0 になってしまい、意図したものと違うことがあるので注意が必要。

/db/migrate/example.rb
def up
  change_column_default :テーブル名, :カラム名, nil
end

def down
  change_column_default :テーブル名, :カラム名, 1
end

長さ

/db/migrate/example.rb
# varchar(12)
change_column :テーブル名, :カラム名, :string, limit: 12

コメント

Rails5からコメントを書けるようになった。

/db/migrate/example.rb
change_column :テーブル名, :カラム名, comment: "コメントです"

小数部の精度を指定する

MySQL5.6.4以降、datetime型で小数部(ミリ秒)の精度指定をサポートしている。Railsも合わせてミリ秒に対応させているので、基本的には指定したほうが良さげ。

/db/migrate/example.rb
def change
  create_table :hoges do |t|
    t.datetime :hoge_date, precision: 6

    t.timestamps precision: 6
  end
end

カラム名を変更する

rename_column :テーブル名, :変更前のカラム名, :変更後のカラム名

この時、対象のカラムにインデックスがある場合、そちらも自動的に変更してくれる。便利。

カラムを追加/削除する

piyoっていうstringなカラムを追加する。追加の場合は、作成時と同じでカラムを予め指定して作ることができる。

command
$ rails g migration AddColumnToUser piyo:string
/db/migrate/20140909095843_add_column_to_user.rb
class AddColumnToUser < ActiveRecord::Migration
  def change

    # 追加
    add_column :users, :piyo, :string

    # 削除
    remove_column :users, :piyo, :string

    # まとめて削除
    remove_columns :users, :column_1, :column_2 [, ...]

    # 追加する場所を指定する場合
    add_column :users, :piyo, :string, :after => :uuid
  end
end

インデックスを追加/削除する

Userモデルのnameカラムにインデックス追加したり削除したり。複合ユニークだったり。

command
$ rails g migration AddIndexToUser
/db/migrate/20140909095843_add_index_to_user.rb
class AddIndexToUser < ActiveRecord::Migration
  def change

    # 追加
    add_index :users, :name

    # ユニーク追加
    add_index :users, :name, :unique => true

    # 削除
    remove_index :users, :name

    # 複合インデックスの場合
    add_index :users, [:name, :name2]

    # 複合ユニークの場合
    add_index :user_accounts, [:provider, :uid], :name => 'unique_provider_uid', :unique => true

  end
end

外部キーを作成・削除する

$ rails g model UserAccount user:references

references を指定することで外部キー制約を作ることができる。これで硬めのDBが作れるはず。

class CreateUserAccounts < ActiveRecord::Migration[5.0]
  def change
    create_table :user_accounts do |t|
      t.references :user,  index: true, foreign_key: true

      t.timestamps
    end
  end
end

既存のテーブルに追加する場合は下記のマイグレーションコマンドで外部キーを追加できる。

$ rails g migration AddArticleToUsers article:references
class AddRefUser < ActiveRecord::Migration
  def change
    add_reference :users, :article, foreign_key: true

    # 外部キーの削除はこちら
    remove_foreign_key :users, column: :article_id

    # カラムも一緒に削除する場合はこちら
    remove_reference :users, :article, foreign_key: true
  end
end

ポリモーフィックを作る

Messageモデルをポリモーフィックとして作る。

$ rails g model message messagable:references{polymorphic}  message:text
class CreateMessages < ActiveRecord::Migration[5.0]
  def change
    create_table :messages do |t|
      t.references :messagable, polymorphic: true
      t.text :message

      t.timestamps
    end
  end
end

関連するモデルのリレーションの指定はこうする。

class Message < ActiveRecord::Base
  belongs_to :messagable, polymorphic: true
end

class Company < ActiveRecord::Base
  has_many :messages, as: :messagable
end

class User < ActiveRecord::Base
  has_many :messages, as: :messagable
end

UserとCompanyモデルがMessageモデルを複数所有するような感じ。

zaru
basicinc
マーケティングとテクノロジーで社会のあらゆる問題を解決する集団
https://tech.basicinc.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした