不知道有沒有更漂亮的作法耶..

開發 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) 的話,我自己的方式分成兩種:

  1. 動手 hack ActiveRecord::ConnectionAdapters::MysqlAdapter

    採用這個方式的話,在被你 hack 過的環境下,你的 migration scripts 不用作任何更改,因為我們直接換掉了 id 所採用的資料型態!找到 <ActiveRecord 函式庫目錄>/lib/active_record/connection_adapters/mysql_adapter.rb 這個檔,然後:

    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

    上面的意思把 - 的那列換成 + 的這一列,存檔後,以後你在使用 Migration 來 create_table 時都會使用 BIGINT 作為 primary key 的資料列態了。

  2. 改寫 Migration script

    上述的作法雖然簡捷,但是 code 的可攜性就不高了,一旦 deploy 到別的環境,又要手動 hack 一遍,所以直接寫在 migration script 裡,雖然麻煩但 code 就可以帶著走了。

    假設原本的 script 是寫成這樣:

    create_table :users do |t|
      t.column :userid, :string
      t.column :passwd, :string
    end

    那可以改成:

    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"

    讓它在建 table 時先不用預設的方式產生 id 欄位,而後再用 SQL 的 alter table 指令來生 id 欄位。

如果有人有更好的作法,歡迎指教,謝謝。

 

歷史上的今天