前幾章有介紹過如何透過 Model 建立你要的資料表以及要的欄位,也有提到 Migration
檔,也提到你需要將資料表具現化,也就是在終端機 rails db:mrigate
,這一張就讓我們好好深入研究吧!
Migration
檔是:
以上一章 Book 的例子來看,我們透過 Model 產生了一個 Migration
檔,這個檔案是描述這個資料表的結構,如下:
class CreateBooks < ActiveRecord::Migration[6.1]
def change
create_table :books do |t|
t.string :name
t.text :content
t.timestamps
end
end
end
上述的資訊確認無誤後,可以透過 rails db:migrate
來將這個描述檔具現化。
如果沒有執行這個指令的話,你會看到這樣的錯誤訊息:
你可以選擇按 Run pending migrations
或執行 $ rails db:migrate
,這兩個方法是一樣的。
如果執行完 Migrate 後,才發現欄位名字打錯,或是少開一個欄位,這時候該怎麼辦呢?
身為新手的我,下意識進到剛剛的 Migration 檔進行修改,存檔後再執行一次 $ rails db:migrate
,這時發現根本沒有效果。
該怎麼做呢?別擔心,做法有好幾種:
其中一個方法就是執行 rails db:rollback
,當你執行後,會把執行過的 Migration 倒回去,就有點像時光機似的。
如果你要倒轉不只一個 Migration,假設你要一次倒轉 2 個,可以加上 STEP=2
:
$ rails db:rollback STEP=2
注意:
雖然使用 Rollback 可以退回去刪除資料表或刪除欄位,但如果原本就有資料了,請不要使用 Rollback 的方式去修正,我建議新增一個 Migration 來修正。
現在有 books
資料表,但是我想要加一個 price
的整數欄位:
$ rails g migration add_price_to_books
這邊可以看到他幫你建立了一個 Migration
檔:
通常命名會是像以上這樣,你當然可以自己取名,但為了讓人一眼就知道這個 Migration
檔是做了什麼事,還是建議以上面這樣命名。
我們來看看這個檔案裡面有什麼:
class AddPriceToBooks < ActiveRecord::Migration[6.1]
def change
end
end
這邊只幫你產生一個空殼而已,所以我們要在這裡面新增想要的欄位:
class AddPriceToBooks < ActiveRecord::Migration[6.1]
def change
add_column :books, :price, :integer
end
end
add_column
後面的第一個參數 (books) 是「資料表名稱」(不是 Model 名稱!),第二個參數 (price) 是「要新增的欄位名稱」,第三個參數 (integer) 是「資料型態」。
寫完之後要記得執行 $ rails db:migrate
:
如果可以新增,那個就可以移除,作法跟新增相似,但要將前面改成 remove_column
。
這次我想要移除 books
資料表中的 content
的欄位,如下:
$ rails g migration remove_content_to_books
之後會發生的事情,會跟新增的是一模一樣的,這邊就不再贅述了。
我們在裡面寫上想要移除的欄位名稱:
class RemoveContentToBooks < ActiveRecord::Migration[6.1]
def change
remove_column :books, :content, :text
end
end
記得要執行 rails db:migrate
,執行完後:
我們執行完 rails db:migrate
後,我們可以進到 db/schema.rb
來看:
ActiveRecord::Schema.define(version: 2022_10_10_113608) do
create_table "books", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "price"
end
end
這些東西是執行 rails db:migrate
之後產生的,我們可以不定手動修改這個檔案。而這個檔案可以看出每個資料表的名稱、欄位名稱與型態,而這個檔案也會在 Git 版本控制中。
Migration 寫好但還沒存檔就執行會發生什麼事呢?
不會怎樣,只是執行了一個空的 Migration 而已。
在新手階段,有時候會忘記存檔就執行 rails db:migrate
,就會鬧出這樣的烏龍「奇怪,怎麼明明 Migration 檔裡就有寫這些欄位,但為什麼 schema.rb 裡卻沒有」,我建議每次寫完要記得存檔!
我們可以透過 rails db:migrate:status
查看 Migration 狀態,如下:
up
這個 Migration 已執行過。down
這個 Migration 尚未執行。這邊整理一些我常用的相關指令
rails g migration ...
rails d migration ...
rails db:drop
rails db:create
rails db:migrate
rails db:migrate:status
參考資料: