[Rails] Active Record Migration (Database Migration)
參考資料:Active Record Migrations @ RailsGuides
# CLI
# 會去執行 ./lib/tasks/dev.rake,需先設定
$ bin/rails dev:build
# 把資料庫砍掉重建
$ bin/rails db:drop db:create db:migrate db:seed
# ./db/migrate/20170919064947_add_need_eticket_to_activities.rb
def change
# add_column :table_name, :column_name, :type, :options
add_column :activities, :need_eticket, :boolean, {comment: '是否使用電子票券', default: false}
end
使用 jsonb
$ rails g migration enable_hstore_extension
# migration 檔案中放入以下內容
enable_extension 'hstore'
使用 uuid
$ rails g migration enable_uuid_extension
# migration 檔案中放入以下內容
enable_extension 'uuid-ossp'
enable_extension 'pgcrypto'
觀念
Migration 是用來描述「資料庫的架構長什麼樣子」的檔案,它會隨著專案開發的過程中逐漸增加。有了 Migration,記得要執行 rails db:migrate
指令,這樣就會把這些描述轉換成真實的資料表。
你可以把每一次的 migrate 都視為一次新「版本」的資料庫,因為 bin/rails db:migrate
這個指令只會針對還沒執行過的 Migration 檔案有效果,已經做過的 Migration ,再做一次是不會有反應的,所以即使修改同一個 Migration 檔再重新執行是沒用的。
透過 Generator 建立 migration 檔
我們可以利用 rails 中的 generator 來建立 migration 檔,migration 的檔案會存在 db/migrate/
中,其中 migration 檔案的檔名(以小寫底線或大寫駝峰命名)必須和 migration 檔中的 class (以大寫駝峰命名)相對應。
在尚未執行 db:migrate
前,利用 Generator 產生的 migration 檔案都可以在自己新增、移除或修改。
透過 model 和 scaffold Generator 也會自動產生 migration 檔。
Cheat Sheet
$ bin/rails g migration <migration_file_name>
# 建立資料表
$ bin/rails g migration <CREATE_tableName> <column_name: column_type> <column_name: column_type>
# 新增移除欄位
$ bin/rails g migration <ADD_columnname_TO_tableName> <column_name>:<column_type>
$ bin/rails g migration <REMOVE_columnname_FROM_tableName> <column_name>:<column_type>
# 關連式資料表
$ bin/rails g migration <ADD_tableName_REF_TO_tableName> <table_name>:references
$ bin/rails g migration <CREATE_JOIN_TABLE_tableName1_tableName2> <tableName1> <tableName2>
產生一般的 migration 檔案
migration 檔案的名稱可以用大寫駝峰或小寫底線:
# bin/rails g migration <migration_file_name>
bin/rails g migration combine_items_in_cart
建立資料表(CreateXXX)
如果 migration 的檔名是以 create
開頭,例如 CreateProducts
,則會在產生的 migration 檔案中使用 create_table
:
# bin/rails g migration create_tableName <column_name: column_type> <column_name: column_type>
$ bin/rails g migration CreateProducts name:string part_number:string
使用 add_column_to_table 新增欄位
使用關鍵字 add
和 to
可以在 migration 檔中自動增加 add_column
欄位:
# bin/rails g migration <add_columnname_to_tableName> <column_name>:<column_type>
bin/rails g migration add_income_to_candidates income:integer
使用 remove_column_from_table 移除欄位
使用關鍵字 remove
和 from
可以在 migration 檔中自動增加 remove_column
欄位:
# bin/rails g migration <remove_columnname_from_tableName> <column_name>:<column_type>
bin/rails g migration remove_votes_from_candidates votes:integer
將欄位加入 index
若需要將該資料庫欄位設為 index
可以在該欄位後直接加上 :index
,則在該 migration 檔中會自動加上 add_index
:
$ bin/rails g migration AddPartNumberToProducts part_number:string:index
使用 add_table_ref_to_table 將不同資料表關連
檔名為 Add_tableName_ref_to_tableName
搭配關鍵字 references
或 belongs_to
可以將不同資料表間的欄位互相關連,例如 AddUserRefToProducts
,將會在 products 資料表中多出一個 user_id 的欄位:
# bin/rails g migration <ADD_tableName_REF_TO_tableName> <table_name>:references
$ bin/rails g migration AddUserRefToProducts user:references
使用 create_join_table_tableName_tableName
使用關鍵字 join_table
可以建立關連性資料表
# bin/rails g migration CreateJoinTableTable1Table2 table1 table2
$ bin/rails g migration CreateJoinTableProductProductItem product product_item
操作 migration 檔
bin/rails db:create # 依照目前的 RAILS_ENV 環境建立資料庫
bin/rails db:create:all # 建立所有環境的資料庫
bin/rails db:drop # 依照目前的 RAILS_ENV 環境刪除資料庫
bin/rails db:drop:all # 刪除所有環境的資料庫
bin/rails db:migrate # 將 migration 檔產成實際的資料庫檔案
bin/rails db:migrate:status # 檢視哪些 migration 被執行過(up 已執行/down 未執行)
bin/rails db:rollback
bin/rails db:rollback STEP=1
bin/rails db:seed # 把種子資料寫入資料庫中
bin/rails db:setup # 同時執行 migrate 和 seed 指令
bin/rails db:reset # 把 db 重置(drop + setup)
因為 Rollback 通常會造成刪除資料表或是刪除欄位的效果,所以如果原本該資料表或該欄位已經有資料的話,請儘量不要使用 Rollback 方式來修正 Migration,建議直接再新增一個 Migration 來進行修正。