2010-06-19 137 views
20

我想耙db:遷移到我heorku實例,我得到一個錯誤。常見問題解答描述我的錯誤如下:如何更改Heroku中的列類型?

Cannot change column type

Example: PGError: ERROR: column 「verified_at」 cannot be cast to type 「date」

Cause: PostgreSQL doesn’t know how to cast all the rows in that table to the specified type. Most likely it means you have an integer or a string in that column.

Solution: Inspect your records and make sure they can be converted to the new type. Sometimes it’s easier to just avoid using change_column, renaming/creating a new column instead.

現在如何更改此遷移。這是我的問題。對於我的聯繫表,我創建了以下內容:

t.string :date_entered 

在以後的遷移,我請執行下列操作:

change_column :contacts, :date_entered, :date 

這change_column似乎是問題。

我應該改變手工移植嗎?有沒有一種方法可以清理我表格中的數據(我不知道Heroku會識別表格中的數據,因爲我在做一個耙子)。

我顯然需要改變這個值,它在整個我的應用程序中使用。謝謝。

這就是我想要的......想法?

def self.up 
    #change_column :contacts, :date_entered, :date 
    #this fails in postgres, so trying the same outcome 

    rename_column :contacts, :date_entered, :date_entered_old 
    add_column :contacts, :date_entered, :date 
    remove_column :contacts, :date_entered_old 
end 

def self.down 
    add_column :contacts, :date_entered_old 
    remove_column :contacts, :date_entered 
    rename_column :contacts, :date_entered_old, :date_entered 
end 

回答

39

執行以下操作:

  1. 重命名該列的
  2. 創建新的B柱如日期
  3. 舉動來自A的數據到B
  4. 刪除

換句話說

def self.up 
    rename_column :contacts, :date_entered, :date_entered_string 
    add_column :contacts, :date_entered, :date 

    Contact.reset_column_information 
    Contact.find_each { |c| c.update_attribute(:date_entered, c.date_entered_string) } 
    remove_column :contacts, :date_entered_string 
end 
+0

+1 #reset_column_information,這是我以前從未見過的修改和測試版本。這看起來在需要的時候非常罕見。 – jdl 2010-06-19 20:46:36

+0

同上re:reset。 – Angela 2010-06-24 01:39:52

+1

兩年後仍然有效! – 2012-12-06 21:50:26

1

這是西蒙尼Carletti酒店的解決方案

class ModifyContacts < ActiveRecord::Migration 
    def self.up 
    rename_column :contacts, :date_entered, :date_entered_string 
    add_column :contacts, :date_entered, :date 

    Contact.reset_column_information 
    Contact.find(:all).each { |contact| contact.update_attribute(:date_entered, contact.date_entered_string) } 
    remove_column :contacts, :date_entered_string 
    end 
end 
+1

雖然你確實需要'find_each'。你的版本會將整個表讀入內存,而find_each將會得到一些行數。 – clacke 2011-07-07 08:36:21