Ruby on Rails
ActiveRecordの移行
サーチ…
パラメーター
列の種類 | 説明 |
---|---|
:primary_key | 主キー |
:string | 短い文字列データ型。最大文字数のlimit オプションを許可します。 |
:text | より長いテキスト量。最大バイト数のlimit オプションを許可します。 |
:integer | 整数。最大バイト数のlimit オプションを許可します。 |
:bigint | より大きい整数 |
:float | 浮く |
:decimal | 可変精度の10進数。 precision とscale オプションが可能です。 |
:numeric | precision とscale オプションが可能です。 |
:datetime | 日付/時刻のDateTimeオブジェクト。 |
:time | 時間オブジェクト。 |
:date | 日付のDateオブジェクト。 |
:binary | バイナリデータ。最大バイト数のlimit オプションを許可します。 |
:boolean | ブール |
備考
ほとんどの移行ファイルは
db/migrate/
ディレクトリにあります。それらは、ファイル名の冒頭にあるUTCタイムスタンプ(YYYYMMDDHHMMSS_create_products.rb
によって識別されます。rails generate
コマンドは、rails g
短くすることができます。a
:type
がフィールドに渡されない場合、デフォルトは文字列になります。
特定の移行を実行する
特定の移行を上または下に実行するには、 db:migrate:up
またはdb:migrate:down
ます。
特定の移行を開始する:
rake db:migrate:up VERSION=20090408054555
rails db:migrate:up VERSION=20090408054555
特定の移行を停止する:
rake db:migrate:down VERSION=20090408054555
rails db:migrate:down VERSION=20090408054555
上記のコマンドのバージョン番号は、移行のファイル名にある数字の接頭辞です。たとえば、移行20160515085959_add_name_to_users.rb
に移行するには、バージョン番号として20160515085959
を使用します。
結合表を作成する
students
とcourses
間に結合テーブルを作成するには、次のコマンドを実行します。
$ rails g migration CreateJoinTableStudentCourse student course
これにより、次の移行が生成されます。
class CreateJoinTableStudentCourse < ActiveRecord::Migration[5.0]
def change
create_join_table :students, :courses do |t|
# t.index [:student_id, :course_id]
# t.index [:course_id, :student_id]
end
end
end
異なる環境での移行の実行
test
環境で移行を実行するには、次のシェルコマンドを実行します。
rake db:migrate RAILS_ENV=test
Rails 5.0から、 rake
ではなくrails
を使用することができます:
rails db:migrate RAILS_ENV=test
テーブルに新しい列を追加する
users
表に新しい列name
を追加するには、次のコマンドを実行します。
rails generate migration AddNameToUsers name
これにより、次の移行が生成されます。
class AddNameToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :name, :string
end
end
マイグレーション名の形式がAddXXXToTABLE_NAME
で、データ・タイプの列のリストが続く場合、生成されたマイグレーションには適切なadd_column
ステートメントが含まれます。
インデックス付きの新しい列を追加する
新しい索引列email
をusers
表に追加するには、次のコマンドを実行します。
rails generate migration AddEmailToUsers email:string:index
これにより、次の移行が生成されます。
class AddEmailToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :email, :string
add_index :users, :email
end
end
テーブルから既存の列を削除する
users
テーブルから既存の列name
を削除するには、次のコマンドを実行します。
rails generate migration RemoveNameFromUsers name:string
これにより、次の移行が生成されます。
class RemoveNameFromUsers < ActiveRecord::Migration[5.0]
def change
remove_column :users, :name, :string
end
end
マイグレーション名の形式がRemoveXXXFromYYY
場合、データ・タイプの列のリストが続き、生成されたマイグレーションには適切なremove_column
ステートメントが含まれます。
データ型(例:string
)をremove_column
パラメータとして指定する必要はありませんが、これをお勧めします。データ型が指定されていない場合、移行は元に戻せません。
表に参照列を追加する
team
への参照をusers
テーブルに追加するには、次のコマンドを実行します。
$ rails generate migration AddTeamRefToUsers team:references
これにより、次の移行が生成されます。
class AddTeamRefToUsers < ActiveRecord::Migration[5.0]
def change
add_reference :users, :team, foreign_key: true
end
end
その移行によって、 users
表にteam_id
列が作成されます。
追加された列に適切なindex
とforeign_key
を追加する場合は、コマンドをrails generate migration AddTeamRefToUsers team:references:index
。これにより、次の移行が生成されます。
class AddTeamRefToUsers < ActiveRecord::Migration
def change
add_reference :users, :team, index: true
add_foreign_key :users, :teams
end
end
あなたが自動生成Railsのもの以外ご参照列に名前を付けたい場合は、あなたの移行に次の行を追加します(例:あなたが呼び出したいかもしれないUser
作成Post
としてAuthor
でPost
テーブル)
class AddAuthorRefToPosts < ActiveRecord::Migration
def change
add_reference :posts, :author, references: :users, index: true
end
end
新しいテーブルを作成する
カラムname
とsalary
を使用して新しいusers
テーブルを作成するには、次のコマンドを実行します。
rails generate migration CreateUsers name:string salary:decimal
これにより、次の移行が生成されます。
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :name
t.decimal :salary
end
end
end
マイグレーション名がCreateXXX
形式のデータ型とそれに続くデータ・タイプの列のリストである場合、リストされた列を持つ表XXX
を作成するマイグレーションが生成されます。
テーブルに複数の列を追加する
テーブルに複数のカラムを追加するには、 rails generate migration
コマンドを使用rails generate migration
ときに、 field:type
ペアをスペースで区切りfield:type
。
一般的な構文は次のとおりです。
rails generate migration NAME [field[:type][:index] field[:type][:index]] [options]
たとえば、次のようにすると、 name
、 salary
、 email
フィールドがusers
テーブルに追加されます。
rails generate migration AddDetailsToUsers name:string salary:decimal email:string
次の移行が生成されます。
class AddDetailsToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :name, :string
add_column :users, :salary, :decimal
add_column :users, :email, :string
end
end
移行の実行
コマンドを実行する:
rake db:migrate
rails db:migrate
ターゲットバージョンを指定すると、指定されたバージョンに達するまで、必要なマイグレーション(up、down、change)が実行されます。ここで、 version number
は移行のファイル名の接頭辞です。
rake db:migrate VERSION=20080906120000
rails db:migrate VERSION=20080906120000
移行のロールバック
最新の移行をrollback
するには、 change
メソッドを元に戻すか、 down
メソッドを実行down
ます。コマンドを実行する:
rake db:rollback
rails db:rollback
過去3回の移行をロールバックする
rake db:rollback STEP=3
rails db:rollback STEP=3
STEP
は、元に戻す移行の数を指定します。
すべての移行をロールバックする
rake db:rollback VERSION=0
rails db:rollback VERSION=0
テーブルの変更
間違ったスキーマを持つ表を作成した場合、列とそのプロパティーを変更する最も簡単な方法はchange_table
です。次の例を確認してください。
change_table :orders do |t|
t.remove :ordered_at # removes column ordered_at
t.string :skew_number # adds a new column
t.index :skew_number #creates an index
t.rename :location, :state #renames location column to state
end
上記の移行は、テーブルのorders
変更します。変更内容は次のとおりです。
-
t.remove :ordered_at
は、テーブルorders
からordered_at
カラムを削除します。 -
t.string :skew_number
は、orders
表にskew_number
という名前の新しい文字列型列を追加します。 -
t.index :skew_number
はorders
テーブルのskew_number
カラムにインデックスを追加します。 -
t.rename :location, :state
リネームlocation
におけるカラムorders
にテーブルをstate
。
テーブルに一意の列を追加する
新しい一意の列のemail
をusers
に追加するには、次のコマンドを実行します。
rails generate migration AddEmailToUsers email:string:uniq
これにより、次の移行が作成されます。
class AddEmailToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :email, :string
add_index :users, :email, unique: true
end
end
既存の列の型を変更する
移行でRailsの既存の列を変更するには、次のコマンドを実行します。
rails g migration change_column_in_table
これにより、 db/migration
ディレクトリに新しい移行ファイルが作成されます(まだ存在していない場合)。このファイルには、タイムスタンプと、以下の内容を含む移行ファイル名の接頭辞が付けられます。
def change
change_column(:table_name, :column_name, :new_type)
end
より長くより安全な方法
上記のコードは、ユーザーが移行をロールバックすることを防止します。この問題を回避するには、 change
メソッドを別々のup
メソッドとdown
メソッドに分割down
ます。
def up
change_column :my_table, :my_column, :new_type
end
def down
change_column :my_table, :my_column, :old_type
end
移行のやり直し
redo
コマンドを使用して、ロールバックしてから再度移行することができます。これは、基本的に、 rollback
タスクとmigrate
タスクを組み合わせたショートカットです。
コマンドを実行する:
rake db:migrate:redo
rails db:migrate:redo
STEP
パラメーターを使用すると、複数のバージョンに戻ることができます。
たとえば、3つの移行に戻るには:
rake db:migrate:redo STEP=3
rails db:migrate:redo STEP=3
デフォルト値の列を追加する
次の例では、列admin
をusers
表に追加し、その列にデフォルト値false
指定します。
class AddDetailsToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :admin, :boolean, default: false
end
end
PostgreSQLなどの大きなテーブルでは、デフォルトの移行で長時間かかる場合があります。これは、新しく追加された列のデフォルト値で各行を更新する必要があるためです。これを回避し(展開中のダウンタイムを減らすために)、移行を3つのステップに分けることができます。
- 上記と同様の
add_column
-migrationを追加しますが、デフォルトは設定しません - アプリケーションの実行中にrakeタスクまたはコンソールに列をデプロイして更新します。アプリケーションが、その列に新しい/更新された行のデータをすでに書き込んでいることを確認してください。
- 別の
change_column
マイグレーションを追加します。これにより、その列のデフォルトが希望のデフォルト値に変更されます
ヌル値を禁止する
テーブルの列にnull
値を禁止するには、次のように:null
パラメータを移行に追加します。
class AddPriceToProducts < ActiveRecord::Migration
def change
add_column :products, :float, null: false
end
end
移行ステータスの確認
実行することで移行の状態を確認できます
rake db:migrate:status
rails db:migrate:status
出力は次のようになります。
Status Migration ID Migration Name
--------------------------------------------------
up 20140711185212 Create documentation pages
up 20140724111844 Create nifty attachments table
up 20140724114255 Create documentation screenshots
up 20160213170731 Create owners
up 20160218214551 Create users
up 20160221162159 ********** NO FILE **********
up 20160222231219 ********** NO FILE **********
statusフィールドの下にあるup
は、移行が実行down
ことを意味し、 down
は、移行を実行する必要があることを意味します。
hstore列を作成する
Hstore
カラムは、設定を保存するのに便利です。拡張機能を有効にした後はPostgreSQLデータベースで利用できます。
class CreatePages < ActiveRecord::Migration[5.0]
def change
create_table :pages do |t|
enable_extension 'hstore' unless extension_enabled?('hstore')
t.hstore :settings
t.timestamps
end
end
end
自己参照を追加する
自己参照は、階層ツリーを構築するのに便利です。これは、移行時にadd_reference
して実現できます。
class AddParentPages < ActiveRecord::Migration[5.0]
def change
add_reference :pages, :pages
end
end
外部キー列はpages_id
ます。外部キーの列名を決定する場合は、最初に列を作成してから参照を追加する必要があります。
class AddParentPages < ActiveRecord::Migration[5.0]
def change
add_column :pages, :parent_id, :integer, null: true, index: true
add_foreign_key :pages, :pages, column: :parent_id
end
end
配列列を作成する
array
列はPostgreSQLでサポートされています。 Railsは自動的にPostgreSQL配列をRuby配列に変換します。逆もまた同様です。
array
列を含む表を作成します。
create_table :products do |t|
t.string :name
t.text :colors, array: true, default: []
end
既存のテーブルにarray
カラムを追加する:
add_column :products, :colors, array: true, default: []
array
列のインデックスを追加する:
add_index :products, :colors, using: 'gin'
既存のデータにNOT NULL制約を追加する
外部キーcompany_id
をusers
テーブルに追加し、そのテーブルにNOT NULL
制約を設定したいとします。 users
既にデータがある場合は、複数の手順でこれを行う必要があります。
class AddCompanyIdToUsers < ActiveRecord::Migration
def up
# add the column with NULL allowed
add_column :users, :company_id, :integer
# make sure every row has a value
User.find_each do |user|
# find the appropriate company record for the user
# according to your business logic
company = Company.first
user.update!(company_id: company.id)
end
# add NOT NULL constraint
change_column_null :users, :company_id, false
end
# Migrations that manipulate data must use up/down instead of change
def down
remove_column :users, :company_id
end
end