2013-06-30 14 views
13

我想在我的「orders」表中添加一個名爲「payment_type」的列。將列添加到表中並修復Rails中現有記錄的值

這裏是我到目前爲止遷移:

def change 
    add_column :orders, :payment_type, :string 
end 

我想這payment_type保存值「正常」的所有當前在數據庫中的記錄。但是,不是爲了將來的記錄。我不想爲將來的記錄默認值。我怎樣才能做到這一點?

回答

30

當你只是想爲設定值的所有現有的記錄,你可以使用update_all,比上循環的順序排列的所有實例快得多,因爲它僅使用數據庫語句,並沒有實例化所有訂單:

def up 
    add_column :orders, :payment_type, :string 
    Order.reset_column_information 
    Order.update_all(payment_type: 'normal') 
end 

def down 
    remove_column :orders, :payment_type 
end 

update_all不調用任何驗證或觸發器。

+7

我建議不要使用主Order類,而應該在遷移中定義一個存根Order類,否則如果Order類不再存在,遷移將在以後停止。 –

+1

即使您可以使用更改方法來代替上下方法。這上面塊將變爲 DEF改變 add_column:訂單:payment_type,:字符串 Order.reset_column_information Order.update_all(payment_type: '正常') 結束 – Amit

+0

對不起,我貼了錯誤的評論,'change'不工作。 –

2
def change 
    add_column :orders, :payment_type, :string 
    Order.all.each do |order| 
    order.update_attributes(:payment_type => 'normal') 
    end 
end 
+0

很好的瞭解,你可以在'change'方法做到這一點,不必寫單獨向上和向下的方法。 – contradictioned

+2

我知道這是超舊的,但在遷移中使用ActiveRecord是不明智的。克隆後,模型即時更新,但在遷移期間,數據庫處於較舊狀態。如果將來訂單收到default_scope時發生了某些更改,則無法更新所有記錄(即使創建遷移時default_scope不在那裏)。 –

0

如果你想更新的列棒與移民則上述答案是真棒, ,如果你想在自己的機器上本地更新列,這樣當你共享代碼,那麼其他人將無法看到更新後的屬性,簡單轉至Rails的控制檯和環...

orders = Order.all 

orders.each do |o| 
    o.update_attribute(:payment_type, 'normal') 
end 

軌道4

+1

也可以在控制檯中使用'Order.update_all(payment_type:'normal')',除非您需要驗證(在這種簡單情況下不太可能)。這是更快,見上文,這是一個班輪。 –

+0

awww,它足夠酷,謝謝你,上面的答案投票,它也輝煌... – Awais

1

我認爲最簡單的方法做到這一點:

class AddStateToSites < ActiveRecord::Migration[5.1] 
     def up 
     add_column :sites, :state, :string, default: :complete # sets default value for existed records 
     change_column :sites, :state, :string, default: nil # changes default value for next 
     end 

     def down 
     remove_column :sites, :state 
     end 
    end 

這檢查控制檯後:

>> Site.last.state 
    Site Load (0.6ms) SELECT "sites".* FROM "sites" ORDER BY "sites"."id" DESC LIMIT $1 [["LIMIT", 1]] 
=> "complete" 
>> Site.new.state 
=> nil 
0

正如其他人所說它不依賴於可能在將來被移除類好習慣,因爲它的制動在這一點上遷移。

相反,我用它來直接執行原MySQL的:

execute "UPDATE `orders` SET `payment_type` = 'normal'" 
相關問題