Creating and Running Migration
在每一個migration file 的前面,有一個三位數的數字,和一個underscore,這個三位數的數字是migration在應用時的版本值。
我們可以餵了新增一個column而新增一個migration file,如此是為了version control。可是當file 多時,會否管理又是一個問題?
當執行rake db::migrate時,這個task首先會檢查db中的schema_info table,以取得目前的version。如果schema_info不存在,則會建立這個table,並設定version 這個column的值為0。
在schema_info這個table中,只有一個column,column name為version。也只有一個row,存放目前的migration version。
如果schema_info table以存在,rails會將值讀出來,然後檢查db/migrate 目錄中所有檔案,是否有檔案的名稱的首三位數字比schema_info table中的version數字大的,如果有,則依序執行他,並改變db。當完成後,便將最後一個數字存入schema_info table中。
強制migrate到某個版本:rake db:migrate VERSION=10
如果數字大於目前的版本,則會將db/migrate目錄中,首三碼的數字是介於目前的版本號碼到指定號碼間的檔案,由小到大執行up method,修改db。
如果數字小於目前的版本,則會將db/migrate目錄中,首三碼的數字是介於目前的版本號碼到指定號碼間的檔案,由大到小執行down method,修改db。
最後都會將schema_info version的數字改為最後執行的編號。
Anatomy of a Migration
Migration class是ActiveRecord::Migration的subclass,其中需包含兩個method up 與 down。
Migration 支援的column type: binary, bo0lean, date, datetime, decimal, float, integer, string, text, time, timestamp。
每一個column有一些選項可以坐設定:
:null => true/false 如果是false,則該column不可以是null。
:limit => size 設定這個column的值得size,例如string的字元數。
Default => value 設定預設值。
在decimal這個column type另有兩個選項可以設定:precision /scale
:precision => 5 定義這個數字有幾位數
:scale => 2 定義小數點後有幾位
ex. add_column

rders, :price, :decimal, :precision=>8, :scale=>2
其範圍是999999.99~-999999.99
add_column

rders, :placed_at, :datetime, :default=>Time.now
因為default value只會在migrate執行時計算一次,所以上述的statement的預設值都是一樣的時間,就是migrate的時間。
如果要解決這個問題,只需將此column name設為created_at,type設為timestamp。
Renaming Column
我們可以利用rename_column來修改column name。
ex. rename_column

rders, :e_mail, :customer_email
其中第一個參數是table name,第二個是舊名稱,第三個是新名稱
Changing Columns
利用change_column method,我們可以修改column type,以及改變某個column的選項。
ex. 將某個type為integer的column改為integer。
def self.up
change_column

rders,

rder_type, :string, :null=>false
end
如此一來,原本在這個column中的數字,就會被改為字串,ex. 123=> '123'
那self.down我們要怎麼寫呢?我們可以很直覺得寫
change_column

rders,

rder_type, :integer
可是這樣會有一個問題,就是如果我們在這個column中有不是數字的值,那該怎麼辦,如果這個column可以接受null,那也許不是問題,可是如果不行呢?
這個時候我們就要讓這個migration成為不能回復的動作,Rails提供了一個特別的exception。
def self.down
raise ActiveRecord::IrreversibleMigration
end
Managing Table
Class CreateOrderHistories < ActiveRecord::Migration
def self.up
create_table

rder_histories do |t|
t.column

rder_id, :integer, :null=>false
t.column :create_at, :timestamp
end
end
def self.down
drop_table

rder_histories
end
end
create_table method 會取得一個table name 與一個block,這個block會透過一個表格定義物件(Table definition object)來定義每一個column。
在create_table中,Migration會自動加入id這個column,並設定為primary key,所以我們無須另外定義。
在create_table中我們可以加入一些選項做設定:
force => true, migration在建立這個table前會先將同名的table刪除。
转自
http://tw.myblog.yahoo.com/weijenlu/article?mid=31&prev=33&next=30&l=a&fid=9