有时你在写迁移任务的时候可能会不小心写错,如果你已经执行了这个迁移任务,那么, 你就不能单纯地把它修改一下再重新执行一次, Rails 会认为这个迁移任务已经执行过了, 所以执行 rake db:migrate 时不会做任何操作。你应该先把写错的那个迁移任务回滚(可以执行 rake db:rollback),然后修改你的migration再执行 rake db:migrate 去 执行正确的版本。
新增一個 Migration 檔案
rails g migration migration_name
migration_name 常見的命名方式有Add欄位名To表格名
或是Remove欄位名To表格名
,不過這沒有一定,能描述目的即可。
rails generate model Product name:string description:text
rails generate migration AddPartNumberToProducts
rails generate migration AddPartNumberToProducts part_number:string
rails generate migration RemovePartNumberFromProducts part_number:string
對資料表做修改:
- create_table(name, options) 新增資料表
- drop_table(name) 移除資料表
- rename_table(old_name, new_name) 修改資料表名稱
- change_table 修改資料表欄位
個別修改資料表欄位:
- add_column(table, column, type, options) 新增一個欄位
- rename_column(table, old_column_name, new_column_name) 修改欄位名稱
- change_column(table, column, type, options) 修改欄位的型態(type)
- remove_column(table , column) 移除欄位
新增、移除索引:
- add_index(table, columns, options) 新增索引
- remove_index(table, index) 移除索引
記得將所有外部鍵 foreign key 加上索引
Rails中的型態 | 說明 | MySQL | Postgres | SQLite3 |
---|---|---|---|---|
:string | 有限長度字串 | varchar(255) | character varying(255) | varchar(255) |
:text | 不限長度文字 | text | text | text |
:integer | 整數 | int(4) | integer | integer |
:float | 浮點數 | float | float | float |
:decimal | 十進位數 | decimal | decimal | decimal |
:datetime | 日期時間 | datetime | timestamp | datetime |
:timestamp | 時間戳章 | datetime | timestamp | datetime |
:time | 時間 | time | time | datetime |
:date | 日期 | date | date | date |
:binary | 二進位 | blob | bytea | blob |
:boolean | 布林值 | tinyint | boolean | boolean |
:references | 用來參照到其他Table的外部鍵 | int(4) | integer | integer |
下面的列表展示了sql和ruby间的数据类型对应关系:
SQLType Ruby Class SQLType Ruby Class
int, integer Fixnum float, double Float
decimal, numeric Float char, varchar, string String
clob, blob, text String datetime, time Time
interval, date Date Boolean 后面详细介绍
有一个潜在的可能是关于decimal的,在数据库里,使用decimal的列来存储number和fix number型,Active Record将decimal映射成Float类的对象,尽管这样可以应用于大多数应用,浮点数是不精确的,在对这一类型的属性进行一系列操作的时候,可能会发生舍入的错误,你也许可以使用integer类型来作为替代方案,例如,存储货币型的时候可以将元,角,分,分别存入不同的字段。做为一种选择,你可以使用聚合(aggregations),使用多个分开的字段来构建货币类型。
另外,欄位也還有一些參數可以設定:
:null
是否允許NULL,預設是允許:default
預設值:limit
用於string、text、integer、binary指定最大值
Migration 搭配的 Rake 任務
- rake db:create 依照目前的 RAILS_ENV 環境建立資料庫
- rake db:create:all 建立所有環境的資料庫
- rake db:drop 依照目前的 RAILS_ENV 環境刪除資料庫
- rake db:drop:all 刪除所有環境的資料庫
- rake db:migrate 執行Migration動作
- rake db:rollback STEP=n 回復上N個 Migration 動作
- rake db:migrate:up VERSION=20080906120000 執行特定版本的Migration
- rake db:migrate:down VERSION=20080906120000 回復特定版本的Migration
- rake db:version 目前資料庫的Migration版本
- rake db:seed 執行 db/seeds.rb 載入種子資料
如果需要指定Rails環境,例如production,可以輸入 RAILS_ENV=production rake db:migrate
bulk參數
:bulk => true
可以讓變更資料庫欄位的Migration更有效率的執行,如果沒有加這個參數,或是直接使用add_column
、rename_column
、remove_column
等方法,那麼Rails會拆開SQL來執行
要变更现有的数据表,可以用 create_table 的类似方法 change_table。它的用法跟create_table 差不多,但它的代码块有更多的方式。例如:
change_table :products do |t| t.remove :description , :name t.string :part_number t.index :part_number t.rename :upccode , :upc_code end |
移除了两个字段 description 和 name,创建了一个 part_number 的字符串类型字段并 为其添加了索引。最后重命名了 upccode 字段。
在一些情况下,Rails会知道如何去恢复所做的改变,使用change方法可以让我们不用同 时写up和down方法。目前来说change方法只支持以下migration的定义:
- add_column
- add_index
- add_timestamps
- create_table
- remove_timestamps
- rename_column
- rename_index
- rename_table
如果你需要使用其他方法,那么你就不能使用change方法而需要同时写up和down方法。
Migration里面的down方法能复原up方法所造成的变更。也就是说如果执行了up然后 再执行down,那么数据库的schema应该会没有改变。所以说,如果用up建立一个数据表, 就应该在down方法中删除它。明智的做法会使用跟up完全相反的顺便来做这些事情。
Rails提供一系列rake任务来执行migrations。第一个跟migration相关的rake任务是 rake db:migrate。它最基本有用法就是单纯地执行所有还没执行migrations的up或者 change方法。若所有migrations都执行过了,它就会直接结束。执行的顺序是按照migration 的日期。
值得注意的是执行db:migrate也会一起执行db:schema:dump,去更新db/schema.rb文件, 以便跟数据库的结构同步。
如果你要migrate到某个特定版本,Active Record会执行所需的migrations(up,down,change) 直到到达指定的版本为上。所谓版本就是migration文件名前面的那串数字。例如要迁移到 版本20080906120000,只需执行:
$ rake db:migrate VERSION=20080906120000 |
如果指定的版本大于当前的版本(往上迁移),那么就会执行up方法到包含指定版本在内的 所有版本。如果是往下迁移的话则会执行所有down方法,但不包括指定版本本身。
rake db:rollback
如果你需要执行一个指定的migration的up或down方法,那么你可以用db:migrate:up和db:migrate:down这两个任务。你只需指定版本号,就可以触发它的up或down方法:
$ rake db:migrate:up VERSION=20080906120000 |
以上会执行20080906120000这个版本的migration的up方法。它会去确认这个migration之前有 没有跑过,所以,如果Active Record认为20080906120000已经跑过,那么执行 db:migrate:up VERSION=20080906120000将不会做任何操作。