2012-09-27 92 views
1

我想寫一個遷移,它看起來是這樣的:在rails遷移中設置不同的默認值?

class AddStatusToWorks < ActiveRecord::Migration 
    def self.up 
    change_table :works do |t| 
     t.string :status 
    end 
    end 

    def self.down 
    change_table :works do |t| 
     t.remove :status 
    end 
    end 
end 

事情是,我想設置基於一個布爾值,這是已經在表中「地位」不同的默認值「完成。」如果complete = true,則status =「complete」。如果不是,狀態=「正在進行中」。 (我想要一個字符串,而不是像布爾值一樣保持完整的原因是因爲我希望能夠有兩種以上的可能狀態。)任何想法如何做到這一點?我只是堅持一條if語句像這樣

change_table :works do |t| 
     t.string :status 
      if (:complete == true) 
       :value => "complete" 
      else 
       :value => "wip" 
end 

呃,這樣看起來不太對勁。我google了一下,發現你可以設置:默認值,但那不是我想要的。任何想法/幫助將是可愛的。謝謝!

+0

所以,你想基於'complete'的當前值來初始化'status'嗎?那麼新排呢? –

+0

呃...新排?我在這方面略顯無力,對不起。 –

+0

等等!你的意思是新行是否在數據庫的未來條目中?在這些情況下,用戶會在創建新工作時設置一個值。只是數據庫中已經有很多條目了,我想知道是否有自動設置它們的值的方法。 –

回答

2

根本不需要默認值,您只需添加新列併爲其賦值即可。像這樣的東西應該工作:

def self.up 
    change_table :works do |t| 
     t.string :status 
    end 
    Works.reset_column_information 
    Works.where(:complete => true).update_all(:status => 'complete') 
    Works.where(:complete => [false, nil]).update_all(:status => 'wip') 
end 

Migrations Guide的信息,reset_column_information

你也能做到這一點直接在數據庫中,但你必須要小心不同的布爾表示(PostgreSQL的希望't''f',MySQL的希望10,SQLite的希望10但Rails的錯誤使用't''f'。 ..):

t = connection.quote(true) 
connection.execute(%Q{ 
    update works 
    set status = case complete 
    when #{t} then 'complete' 
    else 'wip' 
    end 
}) 
+0

所以你可以使用「where」來選擇信息,而不是if/else。哦,那看起來很棒,正是我要找的。非常感謝! –

+0

對,你使用'where'來告訴ActiveRecord你在找什麼,然後'update_all'把它變成數據庫中的'UPDATE ...'。 –

+0

@ user1447477:請記住標記可幫助您「接受」的答案。 –

0

請記住,創建記錄時會立即創建默認值,因此還沒有包含默認值字段的值。您可能想要將這種邏輯轉移到您的模型中。也許在ActiveRecord回調中,即before_validation或before_save。

+0

啊......嗯。好的。所以基本上,創建該表的if語句,然後在模型中,做這樣的事情: '高清edit_status 如果self.complete =真 self.status =「完成」 其他 self.status =「WIP 「' then before_save:edit_status 那樣嗎? –

+0

welp,那失去了很多的格式。呃。無論如何,在遷移中沒有辦法直接做到這一點?因爲我想讓默認值設置一次,然後用戶可以直接編輯它們。如果我使用before_save,每次用戶編輯任何內容時都不會觸發:works? –