不知道有沒有更漂亮的作法耶..
開發 Ruby on Rails 的人很多都會利用 ActiveRecord::Migration 來建立 database 中的 table,而 Migration 的好處是它幫你制定好了很多「資料型態」,讓你在寫 create table 的 script 時,不用特別考慮底層是用哪一套資料庫系統而煩惱 型態的問題。
而 Migration 中的 create_table 這個 method 會自動幫你的 table 設立一個 id
的欄位作為 primary key,若你的資料庫是採用 MySQL 的話,它的資料型態會使用 int(11)
,但若是想要把它改為使用 BIGINT
(64-bit int) 的話,我自己的方式分成兩種:
-
動手 hack ActiveRecord::ConnectionAdapters::MysqlAdapter
採用這個方式的話,在被你 hack 過的環境下,你的 migration scripts 不用作任何更改,因為我們直接換掉了 id 所採用的資料型態!找到
這個檔,然後:/lib/active_record/connection_adapters/mysql_adapter.rb
[code lang=”ruby”]
def native_database_types #:nodoc:
{
– :primary_key => “int(11) DEFAULT NULL auto_increment PRIMARY KEY”,
+ :primary_key => “bigint DEFAULT NULL auto_increment PRIMARY KEY”,
:string => { :name => “varchar”, :limit => 255 },
:text => { :name => “text” },
:integer => { :name => “int”, :limit => 11 },
:float => { :name => “float” },
:decimal => { :name => “decimal” },
:datetime => { :name => “datetime” },
:timestamp => { :name => “datetime” },
:time => { :name => “time” },
:date => { :name => “date” },
:binary => { :name => “blob” },
:boolean => { :name => “tinyint”, :limit => 1 }
}
end
[/code]
上面的意思把-
的那列換成+
的這一列,存檔後,以後你在使用 Migration 來 create_table 時都會使用 BIGINT 作為 primary key 的資料列態了。 -
改寫 Migration script
上述的作法雖然簡捷,但是 code 的可攜性就不高了,一旦 deploy 到別的環境,又要手動 hack 一遍,所以直接寫在 migration script 裡,雖然麻煩但 code 就可以帶著走了。
假設原本的 script 是寫成這樣:
[code lang=”ruby”]
create_table :users do |t|
t.column :userid, :string
t.column :passwd, :string
end
[/code]
那可以改成:
[code lang=”ruby”]
create_table :users, :id => false do |t|
t.column :userid, :string
t.column :passwd, :string
end
execute “alter table users add column id bigint DEFAULT NULL auto_increment PRIMARY KEY”
[/code]
讓它在建 table 時先不用預設的方式產生 id 欄位,而後再用 SQL 的 alter table 指令來生 id 欄位。
如果有人有更好的作法,歡迎指教,謝謝。
base on 你的寫法,我做了一點小小修改↓
create_table :accounts do |t|
t.string :password
t.string :name
t.timestamp :birthday
t.timestamps
end
execute “alter table accounts modify id varchar(32) not null”
我的做法是還是讓Ruby自動create id,然後再去修改id欄位的data type
本例是要把id改為varchar(32) not null的data type(不用加primary key)
因為我比較習慣primary key欄位擺在table的第一個 😛
不過我比較過兩個寫法,你的寫法run的速度會快一點 😛
== 2 CreateAccounts: migrating ==============================
— create_table(:accounts)
-> 0.0790s
— execute(“alter table accounts modify id varchar(32) not null”)
-> 0.1560s
== 2 CreateAccounts: migrating ==============================
— create_table(:accounts, {:id=>false})
-> 0.0780s
— execute(“alter table accounts add column id varchar(32) not null primary key”)
-> 0.1100s
不過以coding要key的字數來說,我的寫法會比較短一些 XD
不過我覺得應該要有更漂亮的做法才對
可是上Ruby on Rails Talk的群組裡找沒有
有人是說id用serial的data type是Rails的慣例
所以不要將它的data type改變比較好… @@
create_table :table_test2, :force=>true, :id=>false do |t|
t.column :test_id, :primary_key
t.column :name, :string, :limit=>512
end
change_column :table_test2, :test_id, :number
这样做也可以的,我是使用oracle的。
直接写sql语句,可能在不同的数据库上运行有兼容性的问题。