Ruby on Rails/ActiveRecord/Migrations
[1] 遷移旨在解決向資料庫推出更改的問題。透過在 Ruby 檔案中定義對資料庫模式的更改,開發團隊可以確保對資料庫的所有更改都經過適當的版本控制。此外,遷移還有助於確保將更改推出給其他開發人員以及其他伺服器(開發、QA、生產)以一致且可管理的方式進行處理。
您可以使用以下方法獨立構建遷移
ruby script/generate migration Category
並在之後編寫特定的命令(如果您想建立自定義 SQL,這是最佳選擇),或者您可以建立一個包含遷移的模型,使用以下方法:
ruby script/generate model Category name:string amount:integer
控制檯告訴您建立了一些檔案,而另一些檔案已經存在。如前所述,Rails 永遠不會覆蓋現有檔案,除非另有說明。
現在讓我們看看遷移
# 20090409120944_create_categories.rb
class CreateCategories < ActiveRecord::Migration
def self.up
create_table :categories do |t|
t.string :name
t.integer :amount
t.timestamps
end
end
def self.down
drop_table :categories
end
end
首先,檢視檔案前面的數字(20090409120944)。這是您的檔案的時間戳,對於建立資料庫表非常重要。此時間戳始終不同,具體取決於建立遷移的確切時間。其背後的理念是擁有所有遷移的“歷史記錄”。
但為什麼這很重要呢?
想象一下,您在一個 Rails 專案上工作,並且透過遷移建立表、更改列或從資料庫中刪除列。過了一段時間,您的客戶改變了主意,他只想要非常基本的功能,而您已經開始建立高階功能並更改了資料庫。因為您無法記住所有進入資料庫的更改及其順序,所以您要麼花很多時間處理資料庫以獲得“舊”狀態,要麼您必須從頭開始,因為記住並重做所有更改會花費太長時間。這就是遷移派上用場的地方,由於時間戳,Rails 能夠以實際順序識別更改,並且所有更改都可以輕鬆撤消。切勿手動更改時間戳。這肯定會導致問題。有關這些主題的更多資訊,請檢視“管理遷移”部分
說到撤消和重做:請注意遷移中的兩個方法self.up和self.down. 它們的功能完全相反。儘管self.up建立帶有所有列的類別表,self.down從資料庫中刪除(刪除)該表及其所有內容 (!!)。當 Rails 看到遷移尚未移動到資料庫時,它將使用self.up方法,如果您撤消遷移,self.down方法將被執行。這樣,您可以確保始終能夠回到資料庫的過去狀態。請記住,在編寫自己的遷移時,始終包含一個self.up和一個self.down方法以確保資料庫狀態在回滾後保持一致。
好的,讓我們從遷移本身開始
create_table :categories do |t|
t.string :name
t.integer :amount
t.timestamps
end
我們想要建立一個名為 categories 的表(create_table :categories) 它包含一個名稱列和一個金額列。此外,Rails 為我們添加了一個時間戳,它將儲存每行的建立日期和更新日期。Rails 還將建立一個名為model_id 的主鍵,它會隨著每行的新增而自動遞增 (1,2,3,...)。
您可以從多種與 ActiveRecord 匹配的資料型別中進行選擇。最常見的型別是
- string
- text
- integer
- decimal
- timestamp
- references
- boolean
但是等等,我們的資料庫中還沒有單個表或列。我們需要將遷移檔案寫入資料庫。
rake db:migrate
負責這項工作。該命令能夠建立該表以及該表中所有必要的列。此命令不僅限於遷移單個檔案,因此您可以同時遷移無限數量的檔案。Rake 還知道資料庫中已經存在哪些遷移,因此它不會覆蓋您的表。有關更多資訊,請參閱“管理遷移”。
為了在表之間新增連線,我們想要在模型中新增引用。引用類似於外部索引鍵(Rails 預設不使用外部索引鍵,因為並非所有資料庫都能處理外部索引鍵,但您可以編寫自定義 SQL 來使用外部索引鍵),並告訴您的表在哪裡查詢更多資料。
讓我們在已經存在的資料庫中新增另一個模型。我們想要建立一個類別,該類別包含多個產品。因此,我們需要在類別中引用此產品。我們想要建立一個模型
ruby script/generate model Products name:string category:references
並將其插入資料庫
rake db:migrate
請注意類別中的型別 :references。這告訴 Rails 在資料庫中建立一個包含對類別的引用的列。現在,我們的資料庫中有一個category_id用於產品的列。(為了使用這兩個模型,我們需要在模型中新增關聯,請參閱關聯)
我們已經討論了遷移如何幫助您以非常方便的方式組織資料庫。現在,我們將看看它是如何實現的。您已經知道檔名中的時間戳告訴 Rails 遷移是在何時建立的,並且 Rake 知道資料庫中已經存在哪些遷移。
為了將資料庫狀態恢復到之前的樣子,例如當前狀態之前的 5 次遷移,我們可以使用以下命令
$rake db:rollback STEP=5
這將撤消已提交到資料庫的最後 5 次遷移。
要重做最後 5 步,我們可以使用類似的命令
$ rake db:migrate:redo STEP=5
您也可以回滾或重做遷移狀態的特定版本,只需提供時間戳即可
$ rake db:migrate:up VERSION=20080906120000
選擇是要執行 db_migrate:up 方法還是 db_migrate:down 方法
請記住,將資料庫恢復到以前的狀態將完全刪除已經插入的資料!
以下方法可用於在 Ruby 中定義模式更改
- create_table(name, options): 建立一個名為 name 的表,並使該表物件可用於新增列的程式碼塊,其格式與add_column相同。請參閱上面的示例。options 雜湊用於“DEFAULT CHARSET=UTF-8”之類的片段,這些片段將附加到建立表的定義中。
- drop_table(name): 刪除名為 name 的表。
- rename_table(old_name, new_name): 將名為 old_name 的表重新命名為 new_name。
- add_column(table_name, column_name, type, options): 向名為 table_name 的表中新增一個名為 column_name 的新列,指定為以下型別之一::string、:text、:integer、:float、:datetime、:timestamp、:time、:date、:binary、:boolean。可以透過傳遞 options 雜湊(例如 { :default => 11 })來指定預設值。
- rename_column(table_name, column_name, new_column_name): 重新命名列,但保留型別和內容。
- change_column(table_name, column_name, type, options): 使用與add_column.
- remove_column(table_name, column_name): 從名為 table_name 的表中刪除名為 column_name 的列。
- add_index(table_name, column_names, index_type, index_name): 在列(或 index_name(如果指定)上)新增一個新索引,其名稱為列名。指定可選的 index_type(例如 UNIQUE)。
- remove_index(table_name, index_name): 刪除由 index_name 指定的索引。
- rake db:create[:all]: 如果沒有指定 :all,則建立 config/database.yml 中定義的當前 RAILS_ENV 的資料庫。 如果指定 :all,則建立 config/database.yml 中定義的所有資料庫。
- rake db:fixtures:load: 將 fixture 載入到當前環境的資料庫中。 使用 FIXTURES=x,y 載入特定的 fixture
- rake db:migrate [VERSION=n]: 透過 db/migrate 中的指令碼遷移資料庫。 使用 VERSION=n 針對特定版本
- rake db:migrate:redo [STEP=n]: (2.0.2) 透過回滾“STEP”個版本的數量並重新應用遷移來回滾資料庫。
- rake db:migrate:reset: (2.0.2) 刪除資料庫,建立它,然後重新應用所有遷移。 rake db:create 註釋中概述的注意事項適用。
- rake db:reset: 使用 db/schema.rb 刪除並重新建立資料庫。 rake db:create 註釋中概述的注意事項適用。
- rake db:rollback [STEP=N]: (2.0.2) 將遷移回滾 1 或 n 個 STEP。
- rake db:schema:dump: 建立一個 db/schema.rb 檔案,該檔案可以移植地用於 AR 支援的任何資料庫
- rake db:schema:load: 將 schema.rb 檔案載入到資料庫中
- rake db:sessions:clear: 清除 sessions 表
- rake db:sessions:create: 建立一個 sessions 表,用於與 CGI::Session::ActiveRecordStore 一起使用
- rake db:structure:dump: 將資料庫結構轉儲到 SQL 檔案中
- rake db:test:clone: 從當前環境的資料庫模式重新建立測試資料庫
- rake db:test:clone_structure: 從開發結構重新建立測試資料庫
- rake db:test:prepare: 準備測試資料庫並載入模式
- rake db:test:purge: 清空測試資料庫
您可以在任何時候使用以下命令獲取命令列表:rake -T從您的應用程式的根目錄中。
您可以使用以下命令獲得每個任務的更完整描述:
rake --describe task:name:and:options
- ↑ 摘錄修改並從 Steve Eichert 的 Ruby on rails Migrations Explained 文章中重新發布。