2012-12-31 66 views
1

我想學習rails,並且遇到了一些問題。如何進行數據庫遷移創建具有特定屬性的表?

我有一箇舊的sqlite3數據庫,它有一個Accounts表,我之前用一些GUI程序做了。我想看看是否可以通過數據庫遷移重新創建該表。

這裏是什麼我以前(我的目標)的說明:

-- desired 
CREATE TABLE "accounts" (
    "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL DEFAULT (0), 
    "username" TEXT NOT NULL COLLATE NOCASE, 
    "password_hash" BLOB NOT NULL, 
    "creation_time" INTEGER NOT NULL DEFAULT(strftime('%s', 'now')), 
    "expiration_time" INTEGER NOT NULL DEFAULT(strftime('%s', 'now') + 2592000) 
) 

我當前的遷移代碼將無法正常工作。我在某處讀到我可以使用:options來指定ActiveRecord無法封裝的東西,但我可能做錯了。當我使用:default => Time.now.to_i時,它只是硬編碼了一些默認值;當我使用:default => "strftime('%s', 'now')"時,它根本不起作用。

class CreateAccounts < ActiveRecord::Migration 
    def change 
    create_table :accounts do |t| 
     t.column 'username', :text, :null => false, :options => 'COLLATE NOCASE' 
     t.column 'password_hash', :binary, :null => false 
     t.column 'creation_time', :integer, :null => false, :options => "DEFAULT(strftime('%s', 'now'))" 
     t.column 'expiration_time', :integer, :null => false, :options => "DEFAULT(strftime('%s', 'now') + 2592000)" 
    end 
    end 
end 

我最終得到了下表。它看起來像所有的:option值都被忽略。

-- what i actually get 
CREATE TABLE "accounts" (
    "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
    "username" text NOT NULL, 
    "password_hash" blob NOT NULL, 
    "creation_time" integer NOT NULL, 
    "expiration_time" integer NOT NULL 
) 

如何在創建列時指定SQL位?任何幫助將非常感激。

回答

3

您可以執行的最簡單的操作就是執行原始SQ L來定義表格。這看起來是這樣的:

class CreateAccounts < ActiveRecord::Migration 
    def up 
    execute <<-SQL 
    CREATE TABLE "accounts" (
     "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL DEFAULT (0), 
     "username" TEXT NOT NULL COLLATE NOCASE, 
     "password_hash" BLOB NOT NULL, 
     "creation_time" INTEGER NOT NULL DEFAULT(strftime('%s', 'now')), 
     "expiration_time" INTEGER NOT NULL DEFAULT(strftime('%s', 'now') + 2592000) 
    ) 
    SQL 
    end 

    def down 
    remove_table :accounts 
    end 
end 

這樣你最終會得到與以前相同的表格。我不完全確定您是否可以使用當前的遷移DSL來表示這樣的表定義。你應該可以驗證它。如果您使用上面的原始SQL進行遷移,則可以運行rake db:migrate。這應該會生成一個新的db/schema.rb。然後,您可以打開該文件並搜索帳戶表並查看定義。如果包含所有內容,則可以將該定義複製回遷移。

1

的默認值都是因爲:

t.column :creation_time, :integer, :null => false, :default => "strftime('%s', 'now'))" 

整理和NOCASE無法通過紅寶石做,但你可以使用execute方法來運行原始SQL:

execute "ALTER TABLE accounts ADD COLUMN username TEXT NOT NULL COLLATE NOCASE AFTER id 

或者,你可以簡單地將排序規則替換爲:

class Account < ActiveRecord::Base 
    def username=(username) 
    write_attribute :username, username.downcase 
    end 
end 
+0

我試着用':默認=>「的strftime(‘%s’的,‘現在’ ))''你建議的東西,但它只是結果爲0. ''creation_time「integer DEFAULT 0 NOT NULL' –

+0

我的猜測是,它會將所有默認值傳遞給列類型。你可能只需要爲那個使用execute。 – sgrif

1

你的移植看起來不錯。

既然您確實想要學習Rails,我會堅持使用它並嘗試解決具體問題。

對於rails,對於創建和更新的日期/時間戳,你所做的是創建一個名爲updated_at和created_at(或每個_on)的字段,然後當rails使用活動記錄來執行數據庫錶行更新時,它將更新這些字段適當和自動地(或者像某些人所說的那樣自動地)。

這是Rails的基本租戶 - 約定優於配置>選擇正確的名稱和限制,它會爲您執行「重負」。

使用的默認設置情況下,但現在它是硬編碼您的問題使得在反射感,但上面會解決這個問題

相關問題