はじめに
学習中で躓いた箇所を記事にしました.初学者の学習の一助となれば幸いです.
また,内容に不備,間違いがあればご指摘いただければと思います.
環境
Ruby 3.1.2
Rails 6.1.7
目次
1. 基礎知識
2. データベースにテーブルを新設する
2-1. マイグレーションファイルを作成する
2-2. マイグレーションファイルをデータベースに適用する
2-3. データベースのテーブル定義を確認する
3. テーブルのカラムを編集(修正,追加,削除)する
3-1. カラム名を修正する
3-2. カラムを追加する
3-3. カラムを削除する
3-4. マイグレーションファイルの直接編集によりカラムを編集する
3-5. 極力,マイグレーションファイルは直接編集しない
4. まとめ
1. 基礎知識
データベースのテーブルカラムを編集するためには,マイグレーションファイルを作成し,データベースへ適用します.マイグレーションファイルとは,データベースのテーブル仕様(カラム名,データ型等)を記載した.rbファイルです.Railsでは,テーブル変更の度にマイグレーションファイルを作成し保存するため,データベースに適用するファイルを選択することでテーブルのバージョン管理ができます.
2. データベースにテーブルを新設する
2-1. マイグレーションファイルを作成する
まずはテーブル仕様を定義するマイグレーションファイルを作成します.
コマンドで<クラス名(処理内容+テーブル名)> <カラム名>:<データ型>
を指定します.
ここではsamples
という名のテーブルを新設(create)
するため,クラス名はCreateSamples
です.カラム名はname
,データ型はstring
とします.
rails g migration CreateSamples name:string
invoke active_record
create db/migrate/20220925142207_create_samples.rb
db/migrateディレクトリに,以下のマイグレーションファイルが作成されました.
class CreateSamples < ActiveRecord::Migration[6.1]
def change
create_table :samples do |t|
t.string :name
t.timestamps
end
end
end
2-2. マイグレーションファイルをデータベースに適用する
次に以下のコマンドを実行します.
rails db:migrate
== 20220925142207 CreateSamples: migrating ====================================
-- create_table(:samples)
-> 0.0036s
== 20220925142207 CreateSamples: migrated (0.0037s) ===========================
データベースにテーブルが追加されました.
テーブルへ反映された内容は以下のファイルで確認ができます.
ActiveRecord::Schema.define(version: 2022_09_25_142207) do
create_table "samples", force: :cascade do |t|
t.string "name"
中略
end
end
name
カラムがstring
型で適用されました.
2-3. データベースのテーブル定義を確認する
テーブルに確実に反映されているかはデータベースのコンソールで確認します.
rails dbconsole
SQLite version 3.36.0 2021-06-18 18:58:49
Enter ".help" for usage hints.
sqlite>
table一覧を確認するため,以下のコマンドを実行します.
sqlite> .table
ar_internal_metadata samples schema_migrations
samplesテーブルが確認できました.
次にテーブルの定義を確認します.
sqlite> pragma table_info(samples);
0|id|integer|1||1
1|name|varchar|0||0
(略)
マイグレーションファイルの通り,テーブルが定義されていることが確認できました.
以下のコマンドでコンソールを終了します.
sqlite> .exit
3. テーブルのカラムを編集(修正,追加,削除)する
3-1. カラム名を修正する
対応の流れは,テーブル新設時と同様です.
マイグレーションファイルの作成 → マイグレーションファイルの内容確認,必要があれば編集 → データベースへ適用 → 適用状態の確認
ここではカラム名name
をnickname
に変更します.
カラム名を変更する場合は,Rename<現在のカラム名>To<変更後のカラム名>In<テーブル名>
を指定します.
rails g migration RenameNameToNickNameInSamples
invoke active_record
create db/migrate/20220925142914_rename_name_to_nick_name_in_create_samples.rb
作成されたマイグレーションファイルに変更内容を記載します.
rename_column :<テーブル名>, :<現在のカラム名>, :<変更後のカラム名>
をchangeメソッドに追記します.
class RenameNameToNickNameInSamples < ActiveRecord::Migration[6.1]
def change
rename_column :samples, :name, :nickname #ここに変更内容を追記.
end
end
変更内容をデータベースへ適用します.
rails db:migrate
適用結果を確認します.
ActiveRecord::Schema.define(version: 2022_09_25_142914) do
create_table "samples", force: :cascade do |t|
t.string "nickname" #nameがnicknameに変更されました.
(略)
end
end
データベースのテーブル定義も確認します.
$ rails dbconsole
sqlite> pragma table_info(samples);
0|id|integer|1||1
1|nickname|varchar|0|NULL|0
(略)
テーブル定義もname
からnickname
に変更されていることが確認できました.
3-2. カラムを追加する
ここではカラムage
を追加します.
カラムを追加する場合は,Add<追加するカラム名>To<テーブル名> <カラム名>:<データ型> <カラム名>:<データ型>,,,,
を指定します.
rails g migration AddAgeToSamples
invoke active_record
create db/migrate/20220925151011_add_age_to_samples.rb
作成されたマイグレーションファイルの内容を確認します.
add_column :<テーブル名>, :<削除するカラム名>, :<データ型>
がchangeメソッドに記述されています.
内容に不備があればrails db:migrate
する前に修正します.
class AddAgeToSamples < ActiveRecord::Migration[6.1]
def change
add_column :samples, :age, :integer
end
end
変更内容をデータベースへ適用します.
rails db:migrate
== 20220925151011 AddAgeToSamples: migrating ==================================
-- add_column(:samples, :age, :integer)
-> 0.0036s
== 20220925151011 AddAgeToSamples: migrated (0.0038s) =========================
適用結果を確認します.
ActiveRecord::Schema.define(version: 2022_09_25_151011) do
create_table "samples", force: :cascade do |t|
t.string "nickname"
(略)
t.integer "age"
end
end
age
カラムが追加されました.
データベースのテーブル定義も確認します.
$ rails dbconsole
sqlite> pragma table_info(samples);
0|id|integer|1||1
1|nickname|varchar|0|NULL|0
(略)
4|age|integer|0||0
テーブル定義でもage
カラムが追加されていることを確認できました.
3-3. カラムを削除する
ここではカラムage
を削除します.
カラムを削除する場合は,Remove<削除するカラム名>From<テーブル名> <カラム名>:<データ型> <カラム名>:<データ型>,,,,
を指定します.
rails g migration RemoveAgeFromSamples age:integer
invoke active_record
create db/migrate/20220925152911_remove_age_from_samples.rb
作成されたマイグレーションファイルの内容を確認します.
remove_column :<テーブル名>, :<削除するカラム名>, :<データ型>
がchangeメソッドに記述されています.
内容に不備があればrails db:migrate
する前に修正します.
class RemoveAgeFromSamples < ActiveRecord::Migration[6.1]
def change
remove_column :samples, :age, :integer
end
end
変更内容をデータベースへ適用します.
rails db:migrate
== 20220925152911 RemoveAgeFromSamples: migrating =============================
-- remove_column(:samples, :age, :integer)
-> 0.0279s
== 20220925152911 RemoveAgeFromSamples: migrated (0.0280s) ====================
適用結果を確認します.
ActiveRecord::Schema.define(version: 2022_09_25_152911) do
create_table "samples", force: :cascade do |t|
t.string "nickname"
(略)
end
end
age
カラムが削除されました.
データベースのテーブル定義も確認します.
$ rails dbconsole
sqlite> pragma table_info(samples);
0|id|integer|1||1
1|nickname|varchar|0|NULL|0
(略)
テーブル定義でもage
カラムが削除されていることを確認できました.
3-4. マイグレーションファイルの直接編集によりカラムを編集する
マイグレーションファイルを直接編集するためには,rails db:rollback
またはrails db:migrate:down VERSION=**************
でロールバックする必要があります.
ロールバックにより,データベースに未適用状態となるため,マイグレーションファイルを直接編集できるようになります.(データベースに適用されている状態のマイグレーションファイルを直接編集して,rails db:migrate
しても変更内容はデータベースに反映されません.)
以下にマイグレーションファイルの直接編集例を載せます.
カラム名nickname
をfamilyname
に変更することを考えます.
まず,既存のマイグレーションファイルのデータベースへの適用状態を確認します.
rails db:migrate:status
(略)
Status Migration ID Migration Name
--------------------------------------------------
up 20220925142207 Create samples
up 20220925150043 Rename name to nick name in samples
up 20220925151011 Add age to samples
up 20220925152911 Remove age from samples
カラム名をRename
したマイグレーションファイルは上から2段目です.Status
がup
になっています.データベースに適用されていますので,以下のコマンドでロールバックを行います.
rails db:migrate:down VERSION=20220925150043
== 20220925150043 RenameNameToNickNameInSamples: reverting ====================
-- rename_column(:samples, :nickname, :name)
-> 0.0165s
== 20220925150043 RenameNameToNickNameInSamples: reverted (0.0202s) ===========
ロールバックが実行されましたので,再度データベースへの適用状態を確認します.
rails db:migrate:status
(略)
Status Migration ID Migration Name
--------------------------------------------------
up 20220925142207 Create samples
down 20220925150043 Rename name to nick name in samples
up 20220925151011 Add age to samples
up 20220925152911 Remove age from samples
目的のファイルのみStatus
がdown
となっています.
ここでファイルの直接編集が可能になります.
以下のようにカラム名をnickname
からfamilyname
に変更します.
class RenameNameToNickNameInSamples < ActiveRecord::Migration[6.1]
def change
rename_column :samples, :name, :familyname #nickname → familynameに変更
end
end
変更が完了したらデータベースへ適用します.
rails db:migrate
== 20220925150043 RenameNameToNickNameInSamples: migrating ====================
-- rename_column(:samples, :name, :familyname)
-> 0.0150s
== 20220925150043 RenameNameToNickNameInSamples: migrated (0.0151s) ===========
スキーマファイルとテーブル定義を確認します.
ActiveRecord::Schema.define(version: 2022_09_25_164433) do
create_table "samples", force: :cascade do |t|
t.string "familyname"
(略)
end
end
カラム名がnickname
からfamilyname
に変更されました.
データベースのテーブル定義も確認します.
$ rails dbconsole
sqlite> pragma table_info(samples);
0|id|integer|1||1
1|familyname|varchar|0|NULL|0
中略
カラム名がfamilyname
に編集されていることを確認できました.
3-5. マイグレーションファイルの直接編集は非推奨です
マイグレーションファイルを直接編集する方法を載せましたが,この方法は推奨されてません.
Railsガイドに記載がある通り,テーブルカラムの編集を行う場合は,マイグレーションファイルを新設することが基本方針です.
以下,Railsガイドから引用です.
一般に、既存のマイグレーションを直接変更するのはよくありません。既存のマイグレーションを変更すると、自分自身はもちろん、共同作業者も余分な作業を強いられます。さらに、既存のマイグレーションがproduction環境で実行中の場合、ひどい頭痛の種になるでしょう。既存のマイグレーションを直接修正するのではなく、修正用のマイグレーションを新たに作成してそれを実行するのが正しい方法です。これまでコミットされてない(より一般的に言えば、これまでdevelopment環境以外にデプロイされたことのない)マイグレーションを新たに生成し、それを編集するのが害の少ない方法です。
4. まとめ
- マイグレーションファイルを新設し,データベースに適用することで,テーブルを新設し,カラムを編集できます.
- マイグレーションファイルの直接編集によるカラムの編集は非推奨です.
以上です.
皆さんの学習の一助となれば幸いです.
参考