2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

シンプルでやさしいチートシート 【Rails Migration編】

Last updated at Posted at 2020-02-01

はじめに

毎回ググってる気がするので、まとめました。
右側の目次からお探しの用語やコマンドをクリックしてお使いください!:slight_smile:

対象となる読者

  • マイグレーションに苦手意識のある初心者の方
  • 復習も兼ねて基本操作を中心におさらいしたい経験者の方
  • マイグレーション関連でハマりたくない方

###テーブルを作る
modelを作成すると/db/migrate/ 以下にマイグレーションファイルも一緒に作成されます。
この場合クラス名はUsername,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: カラムにコメントを追加します。

ちなみにnulldefaultはコマンドラインで指定できません。

Railsガイド カラム修飾子

データタイプ(型)、カラム修飾子(オプション)を指定してテーブルを作る

  $ rails g model Product name:string:index sku:string{10}:uniq \
                 supplier:references{polymorphic} 'price:decimal{10,2}'                 

indexは追加したいカラムに記述するだけです。
limitpolymorphicは{}内に記述。
precisionscaleはカラムと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

マイグレーションファイルの名前の付け方

カラムを追加、削除、変更する場合、AddColumnToUsersChangeColumnOfUsers
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メソッドを使用してもいいと思います。現場に合わせて適時使い分けていただければと思います。

おわりに

もしこの記事が為になった!という方はフォローやいいねボタンのクリックをしていただけたらとても嬉しいです!:smiley:

参考

Railsガイド
rails generate migrationコマンドまとめ @zaru
Ruby on Railsでテーブルのカラムを追加・削除する方法 @Reasonable Code

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?