【Rails】テーブルやカラムの追加・名前の変更・削除・データ型を変更する方法を実例で解説

rails-prograshi(プロぐらし)-kv Rails
記事内に広告が含まれていることがあります。

Railsのモデルを使って作成したデータベースのテーブルの名前やカラム名を変更する方法と、カラムのデータ型を変更する方法について。

早見表

マイグレーションファイル&モデルの作成

マイグレーションファイルとモデルファイルを生成するときは、rails g modelコマンドを使います。 gはgenerateの省略形です。

rails g <モデル名> <カラム名1:型1> <カラム名2:型2>,,,

ここでのモデル名は基本的にアッパーキャメルケースで記述します(小文字でも生成できます)。命名規則に則り、単数形で記述します。

テーブル名とモデル名の対応

テーブル名とモデル名には命名規則があります。このため、どちらかがわかれば、もう一方もわかります。

項目命名規則詳細
テーブルスネークケース複数形全て小文字の複数形
モデルアッパーキャメルケース単数形単語の冒頭が大文字の単数形

テーブル名とモデル名の

テーブル名モデル名モデルファイル名
clientsClientclient.rb
client_numbersClientNumberclient_number.rb

ファイル生成後はrails db:migrate でデータベースにマイグレーションファイルの内容を反映します。

テーブルやカラムの変更・編集・削除

テーブルやカラムの変更・編集・削除には、rails g migrationコマンドを使います。gはgenerateの省略形です。

rails g migration <クラス名> <カラム名1:型1> <カラム名2:型2>,,,
処理migration命名例Model内メソッド
カラム追加Add<追加するカラム名>To<テーブル名>add_column
カラム削除Remove<カラム名>From<テーブル名>remove_column
テーブル名変更Rename<元のテーブル名>To<変更後のテーブル名>rename_table
テーブル削除Drop<テーブル名>drop_table
カラム名変更Rename<元のカラム名>To<変更後のカラム名>In<テーブル名>rename_column
データ型変更Change<テーブル名><カラム名>To<変更後の型>change_column
インデックス追加AddIndexTo<カラム名>add_index
インデックス削除RemoveIndexFrom<カラム名>remove_index

※それぞれ冒頭大文字(アッパーキャメルケース)で記述します

ファイル生成後はrails db:migrate でデータベースにマイグレーションファイルの内容を反映します。

tips

命名規則は絶対的なものではありません。指定した名前がマイグレーションファイルの中のクラス名になります。

クラス名を見たときに、プロジェクトのメンバーが何の処理かわかるよう命名します。

一定の命名規則を満たしている場合は、マイグレーションファイル生成時に自動で処理を記載してくれます。処理を追加・変更したい場合は、後から手動で書き直します。

注意点

マイグレーション実施後のファイルは基本的に編集はNGです。(ロールバックできなくなるため)

テーブルの内容を変更・修正したい場合は、新たにマイグレーションファイルを生成します。


テーブルにカラムを追加する

既存のテーブルにカラムを追加する場合、rails g migration で実行するコードは次のような形になります。

rails g migration Add<追加するカラム名>To<テーブル名> <カラム名1:型1> <カラム名2:型2>,,,

実際にカラムを追加するには、マイグレーションファイルにadd_columnを追加します。

class Add<追加するカラム名>To<テーブル名> < ActiveRecord::Migration[6.1]
  def change
    add_column :<テーブル名>, :<カラム名>, :<型>
  end
end


実例

clientsテーブルにprojectカラムを追加する場合は次のようになります。

# rails g migration AddProjectToClients project:string
Running via Spring preloader in process 267
      invoke  active_record
      create    db/migrate/20210724072258_add_project_to_clients.rb

生成したマイグレーションファイルは次のようになっています。

class AddProjectToClients < ActiveRecord::Migration[6.1]
  def change
    add_column :clients, :project, :string
  end
end

この状態でマイグレーションを実行すれば、clientsテーブルにprojectカラムが追加できます。

▼マイグレーションの実行

# rails db:migrate
== 20210724072258 AddProjectToClients: migrating ==============================
-- add_column(:clients, :project, :string)
   -> 0.0042s
== 20210724072258 AddProjectToClients: migrated (0.0043s) =====================

以上でカラムの追加は完了です。


テーブルからカラムを削除する

既存のテーブルのカラムを削除する場合、rails g migration で実行するコードは次のような形になります。

rails g migration Remove<カラム名>From<テーブル名> <カラム名1:型1> <カラム名2:型2> <カラム名3:型3>,,,

カラム名:型 を指定しない場合は、型がstringとしてマイグレーションファイルに記載されます。

生成されたマイグレーションファイルには、remove_columnが追加されています。

class Remove<カラム名>From<テーブル名> < ActiveRecord::Migration[6.1]
  def change
    remove_column :<テーブル名>, :<カラム名>, :<型>
  end
end

複数のカラムを削除したい場合は、その分だけremove_columnの行を追加します。

カラム削除時の注意点

カラムを削除するときは、マイグレーションファイルのremove_columnで、テーブルの型を指定する必要があります。

また、オプションがある場合はオプションも指定します。これをしないとロールバックできなくなります。

remove_column :<テーブル名>, :<カラム名>, :<型>, <オプション1>: <値1>, <オプション2>: <値2>,,,
remove_column :posts, :slug, :string, null: false, default: ''

(参考)Rails公式 Changeメソッド remove_column


実例

clientsテーブルのprojectカラム、nameカラム、ageカラムの3つを削除する場合は次のようになります。

# rails g migration RemoveColumnsFromClient project:text name:string age:integer
Running via Spring preloader in process 338
      invoke  active_record
      create    db/migrate/20210724074250_remove_columns_from_client.rb

生成したマイグレーションファイルは次のようになっています。

class RemoveColumnsFromClient < ActiveRecord::Migration[6.1]
  def change
    remove_column :clients, :project, :text
    remove_column :clients, :name, :string
    remove_column :clients, :age, :integer
  end
end

この状態でマイグレーションを実行すれば、clientsテーブルからprojectカラムが削除できます。

▼マイグレーションの実行

# rails db:migrate
== 20210724072900 RemoveProjectFromClients: migrating =========================
-- remove_column(:clients, :project, :text)
-- remove_column(:clients, :name, :string)
-- remove_column(:clients, :age, :integer)
   -> 0.0169s
== 20210724072900 RemoveProjectFromClients: migrated (0.0172s) ================


テーブル名を変更する

既存のテーブルの名前を変更する場合、rails g migration で実行するコードは次のような形になります。

rails g migration Rename<元のテーブル名>To<変更後のテーブル名> <カラム名1:型1> <カラム名2:型2>,,,

マイグレーションファイルにrename_tableを追記します。

注意点

rename_tableはchangeメソッドに対応してないため、upメソッドとdownメソッドで記述する必要があります。


(参考)【Rails】マイグレーションファイルでchangeメソッドが使える定義一覧表

class Remove<カラム名>From<テーブル名> < ActiveRecord::Migration[6.1]
  def up
    rename_table :<元のテーブル名>, :<新しいテーブル名>
  end

  def down
    rename_table :<新しいテーブル名>, :<元のテーブル名>
  end
end

複数のテーブルの名前を変更したい場合は、その分だけrename_tableの行を追加します。


実例

studentsテーブルをpeopleに変更する場合は次のようになります。

# rails g migration RenameStudentsToPeople
Running via Spring preloader in process 400
      invoke  active_record
      create    db/migrate/20210724080344_rename_students_to_people.rb

生成したマイグレーションファイルには何も記述されていないので、 rename_table を追記します。

class RenameStudentsToPeople < ActiveRecord::Migration[6.1]
  def up
    rename_table :students, :people
  end

  def down
    rename_table :people, :students
  end

end

この状態でマイグレーションを実行すれば、studentsテーブルからpeopleテーブルに名前を変更できます。

▼マイグレーションの実行

# rails db:migrate
== 20210724080344 RenameStudentsToPeople: migrating ===========================
-- rename_table(:students, :people)
   -> 0.0143s
== 20210724080344 RenameStudentsToPeople: migrated (0.0144s) ==================

▼Railsコンソールで確認

実際に変更されたかどうかコンソールで確認してみます。

#migration実行前
irb(main):001:0> ActiveRecord::Base.connection.tables
=> ["schema_migrations", "ar_internal_metadata", "students", "clients"]


#migration実行後
# rails c
Running via Spring preloader in process 424
Loading development environment (Rails 6.1.4)
irb(main):001:0> ActiveRecord::Base.connection.tables
=> ["schema_migrations", "ar_internal_metadata", "clients", "people"]


テーブルの名前が変更できていることが確認できました。

railsコンソールを使ってモデル経由でDBを操作する方法については下記をご参考ください。

(参考)【Rails】コンソールからモデルを使ってテーブルの一覧表示やデータ追加・更新・変更・削除する方法(データベース操作)


カラム名を変更する

既存のテーブルのカラム名を変更する場合、rails g migration で実行するコードは次のような形になります。

rails g migration Rename<元のカラム名>To<変更後のカラム名>In<テーブル名>

マイグレーションファイルにrename_columnを追記します。

注意点

rename_columnはchangeメソッドに対応してないため、upメソッドとdownメソッドで記述する必要があります。


(参考)【Rails】マイグレーションファイルでchangeメソッドが使える定義一覧表

class Rename<元のカラム名>To<変更後のカラム名>In<テーブル名> < ActiveRecord::Migration[6.1]
  def up
    rename_column :<テーブル名>, :<古いテーブル名>, :<新しいテーブル名>
  end

  def down
    rename_column :<テーブル名>, :<新しいテーブル名>, :<古いテーブル名>
  end
end

複数のテーブルの名前を変更したい場合は、その分だけrename_columnの行を追加します。


実例

clientsテーブルのnameカラムをclient_nameに変更する場合は次のようになります。

# rails g migration RenameNameToClientNameInClients
Running via Spring preloader in process 478
      invoke  active_record
      create    db/migrate/20210724082720_rename_name_to_client_name_in_clients.rb

生成したマイグレーションファイルには何も記述されていないので、 rename_column を追記します。

class RenameNameToClientNameInClients < ActiveRecord::Migration[6.1]
  def up
    rename_column :clients, :name, :client_name
  end

  def down
    rename_column :clients, :client_name, :name
  end
end

この状態でマイグレーションを実行すれば、studentsテーブルからpeopleテーブルに名前を変更できます。

▼マイグレーションの実行

# rails db:migrate
== 20210724082720 RenameNameToClientNameInClients: migrating ==================
-- rename_column(:clients, :name, :client_name)
   -> 0.0067s
== 20210724082720 RenameNameToClientNameInClients: migrated (0.0069s) =========

▼Railsコンソールで確認

実際に変更されたかどうかコンソールで確認してみます。

#migration実行前
irb(main):003:0> Client.column_names
=> ["id", "created_at", "updated_at", "name", "age"]


#migration実行後
# rails c
Running via Spring preloader in process 424
Loading development environment (Rails 6.1.4)
irb(main):001:0> Client.column_names
=> ["id", "created_at", "updated_at", "client_name", "age"]


カラム名が変更できていることが確認できました。

railsコンソールを使ってモデル経由でDBを操作する方法については下記をご参考ください。

(参考)【Rails】コンソールからモデルを使ってテーブルの一覧表示やデータ追加・更新・変更・削除する方法(データベース操作)


カラムのデータ型を変更する

既存のテーブルのカラムのデータ型を変更する場合、rails g migration で実行するコードは次のような形になります。

rails g migration Change<テーブル名><カラム名>To<変更後の型>

生成されたマイグレーションファイルには何も記載がないので、change_columnを追加します。

注意点

change_columnはchangeメソッドに対応してないため、upメソッドとdownメソッドで記述する必要があります。


(参考)【Rails】マイグレーションファイルでchangeメソッドが使える定義一覧表


また、指定する型によって書き方が変わります

  1. stringやtext
  2. integerやboolean, dateなどに変換する


stringやtext型に変換する

データ型をtextやstringにする場合は次のようにします。

class Rename<元のカラム名>To<変更後のカラム名>In<テーブル名> < ActiveRecord::Migration[6.1]
  def up
    change_column :<テーブル名>, :<カラム名>, :<新しい型>
  end

  def down
    change_column :<テーブル名>, :<カラム名>, :<古い型>
  end
end
注意点

変換後の型にintegerやbooleanを指定する場合は書き方が異なります。この状態でintegerやbooleanを指定すると次のようなエラーが発生します。

Caused by:
ActiveRecord::StatementInvalid: PG::DatatypeMismatch: ERROR: column “age” cannot be cast automatically to type integer
HINT: You might need to specify “USING age::integer”.


integerやboolean、date型に変換する場合

データ型をintegerやboolean、date型などに変換にする場合は次のようにします。

class Rename<元のカラム名>To<変更後のカラム名>In<テーブル名> < ActiveRecord::Migration[6.1]
  def up
    change_column :<テーブル名>, :<カラム名>, :<新しい型>, using: "<カラム名>::<新しい型>"
  end

  def down
    change_column :<テーブル名>, :<カラム名>, :<古い型>, using: "<カラム名>::<古い型>"
  end
end

複数のカラムの型を変更したい場合は、その分だけchange_columnの行を追加します。

point

using: “<カラム名>::<型>” を指定するときの、カラムと型の間のダブルコロンは2つです。1つだとエラーが出ます。

▼エラー例

Caused by:
PG::SyntaxError: ERROR: syntax error at or near “:”
LINE 1: … “clients” ALTER COLUMN “age” TYPE integer USING age:integer


実例

clientsテーブルのageカラムの型をintegerに変更する場合は次のようになります。

# rails g migration ChangeClientsAgeToInteger
Running via Spring preloader in process 513
      invoke  active_record
      create    db/migrate/20210724083954_change_clients_age_to_integer.rb

生成したマイグレーションファイルには何も記述されていないので、 change_column を追記します。

integer型なので、usingを忘れずに記載します。

class ChangeClientsAgeToInteger2 < ActiveRecord::Migration[6.1]
  def up
    change_column :clients, :age, :integer, using: "age::integer"
  end

  def down
    change_column :clients, :age, :string
  end
end

この状態でマイグレーションを実行すれば、ageカラムの型がintegerに変換されます。

▼マイグレーションの実行

# rails db:migrate
== 20210724085421 ChangeClientsAgeToInteger2: migrating =======================
-- change_column(:clients, :age, :integer, {:using=>"age::integer"})
   -> 0.0403s
== 20210724085421 ChangeClientsAgeToInteger2: migrated (0.0405s) ==============



テーブルを削除する

既存のテーブルを削除するには

  1. テーブルの削除
  2. 関連ファイルの削除(手動で行う)
テーブル削除時の注意点

テーブルを削除するときに、rails destroy model <モデル名> を実行するのは非推奨です。

このコマンドを実行するとマイグレーションファイルも削除されるので、ロールバックができなくなります。


テーブルの削除

既存のテーブルを削除する場合、rails g migration で実行するコードは次のような形になります。

rails g migration Drop<テーブル名>

実際にカラムを追加するには、マイグレーションファイルにdrop_tableを追加します。(※デフォルトでは何も記述がありません)

注意点

drop_tableはchangeメソッドに対応していますが、ロールバックを可能にするにはブロック形式で記述する必要があります。(通常は元のカラムの型やオプションをすべて指定します)


(参考)【Rails】マイグレーションファイルでchangeメソッドが使える定義一覧表


対応をしないとエラーが発生します。エラーを回避する書き方はいくつかあります。

(参考)【Rails】エラー対処法:ActiveRecord::IrreversibleMigration: To avoid mistakes, drop_table is only reversible if given options or a block (can be empty).

class <クラス名> < ActiveRecord::Migration[6.1]
  def change
    drop_table :<テーブル名> do |t|
      t.<型1> :<カラム名1>, <オプション: 値>,,,
      t.<型2> :<カラム名2>, <オプション: 値>,,,
      ,,,
    end
  end
end

複数のカラムを削除したい場合は、その分だけdrop_tableの行を追加します。

テーブルを使う予定がない場合

テーブルを使う予定がない場合は、カラムと型をあえて指定せず、ブロック内の処理を空の状態にする方法もあります。

class <クラス名> < ActiveRecord::Migration[6.1]
  def change
    drop_table :<テーブル名> do
    end
  end
end

ロールバックを実行したときは、指定した名前のテーブルがカラムが無い状態で生成されます。


関連ファイルの削除

DBのテーブルが削除できたら、続いて関連するファイルを削除します。削除するのは次の3つです。

  1. modelファイル (app/models/xxx.rb)
  2. testファイル (test/models/xxx_test.rb)
  3. fixturesファイル (test/fixtures/xxx.yml)
注意点

関連ファイルを削除するときに、マイグレーションファイルは削除しないようにします。

マイグレーションファイルを削除するとロールバックが正常にできなくなり、DBの過去の状態を復元できなくなるリスクがあります。

以上でテーブルの削除処理は完了です。


実例

test_camelsというテーブルを削除する場合は次のようになります。

# rails g migration DropTestCamel
Running via Spring preloader in process 358
      invoke  active_record
      create    db/migrate/20210724075541_drop_test_camel.rb

生成したマイグレーションファイルを次のように編集します。

class DropTestCamel < ActiveRecord::Migration[6.1]
  def change
    drop_table :test_camels do |t|
      t.string :name, null: false
    end
  end
end

この状態でマイグレーションを実行すれば、test_camelsテーブルを削除できます。

▼マイグレーションの実行

# rails db:migrate
== 20210724075541 DropTestCamel: migrating ====================================
-- drop_table(:test_camels)
   -> 0.0066s
== 20210724075541 DropTestCamel: migrated (0.0068s) ===========================

▼Railsコンソールで確認

実際に削除されたかどうかコンソールで確認してみます。

#migration実行前
irb(main):002:0> ActiveRecord::Base.connection.tables
=> ["schema_migrations", "ar_internal_metadata", "students", "test_camels", "clients"]


#migration実行後
# rails c
Running via Spring preloader in process 381
Loading development environment (Rails 6.1.4)
irb(main):001:0> ActiveRecord::Base.connection.tables
=> ["schema_migrations", "ar_internal_metadata", "students", "clients"]


削除できていることが確認できました。

drop_tableのロールバック時の注意点など、更に深堀したい方は下記をご参考ください。

【Rails】テーブル削除(drop_table)の注意点!エラー対処法:ActiveRecord::IrreversibleMigration


テーブルの中のデータを追加・更新・変更・削除する方法

テーブルへのカラム追加や削除、変更などスキーマ(DB自体の構造)を変えるにはマイグレーションファイルで処理を行う必要があります。

一方で、テーブル内のデータを追加・更新・変更・削除するには、マイグレーションファイルではなく、モデル経由で行います

Railsでモデルを使ってDBを操作する方法については下記をご参考ください。

(参考)【Rails】コンソールからモデルを使ってテーブルの一覧表示やデータ追加・更新・変更・削除する方法(データベース操作)

タイトルとURLをコピーしました