0
0

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 1 year has passed since last update.

【Rails】データベースのテーブルを新設し,カラムを編集する

Last updated at Posted at 2022-09-26

はじめに

学習中で躓いた箇所を記事にしました.初学者の学習の一助となれば幸いです.
また,内容に不備,間違いがあればご指摘いただければと思います.

環境

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ディレクトリに,以下のマイグレーションファイルが作成されました.

db/migrate/20220925142207_create_samples.rb
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) ===========================

データベースにテーブルが追加されました.
テーブルへ反映された内容は以下のファイルで確認ができます.

db/schema.rb
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. カラム名を修正する

対応の流れは,テーブル新設時と同様です.
マイグレーションファイルの作成 → マイグレーションファイルの内容確認,必要があれば編集 → データベースへ適用 → 適用状態の確認

ここではカラム名namenicknameに変更します.
カラム名を変更する場合は,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メソッドに追記します.

db/migrate/20220925142914_rename_name_to_nick_name_in_create_samples.rb
class RenameNameToNickNameInSamples < ActiveRecord::Migration[6.1]
  def change
    rename_column :samples, :name, :nickname #ここに変更内容を追記.
  end
end

変更内容をデータベースへ適用します.

コマンド
rails db:migrate

適用結果を確認します.

db/schema.rb
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する前に修正します.

db/migrate/20220925151011_add_age_to_samples.rb
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) =========================

適用結果を確認します.

db/schema.rb
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する前に修正します.

db/migrate/20220925152911_remove_age_from_samples.rb
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) ====================

適用結果を確認します.

db/schema.rb
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しても変更内容はデータベースに反映されません.)

以下にマイグレーションファイルの直接編集例を載せます.
カラム名nicknamefamilynameに変更することを考えます.

まず,既存のマイグレーションファイルのデータベースへの適用状態を確認します.

コマンド
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段目です.Statusupになっています.データベースに適用されていますので,以下のコマンドでロールバックを行います.

コマンド
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

目的のファイルのみStatusdownとなっています.
ここでファイルの直接編集が可能になります.
以下のようにカラム名をnicknameからfamilynameに変更します.

db/migrate/20220925150043_rename_name_to_nick_name_in_samples.rb
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) ===========

スキーマファイルとテーブル定義を確認します.

db/schema.rb
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. まとめ

  • マイグレーションファイルを新設し,データベースに適用することで,テーブルを新設し,カラムを編集できます.
  • マイグレーションファイルの直接編集によるカラムの編集は非推奨です.

以上です.
皆さんの学習の一助となれば幸いです.

参考

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?