2010-06-19 41 views
20

Tôi đang cố gắng bẻ khóa db: di chuyển sang thể hiện heorku của tôi và tôi gặp lỗi. Câu hỏi thường gặp đã mô tả lỗi của tôi như sau:Làm cách nào để thay đổi loại cột trong 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.

Làm cách nào để thay đổi quá trình di chuyển này ngay bây giờ. Đây là vấn đề mà tôi có. Đối với bảng hệ của tôi, tôi đã tạo điều sau đây:

t.string :date_entered 

Trong một sự chuyển đổi sau, tôi làm như sau:

change_column :contacts, :date_entered, :date 

change_column này dường như là vấn đề.

Tôi có nên ... thay đổi bằng cách di chuyển đó? Có cách nào tôi có thể làm sạch dữ liệu trong bảng của tôi (tôi không biết Heroku sẽ nhận ra dữ liệu trong bảng bởi vì tôi đang làm một cái cào).

Tôi rõ ràng cần phải thay đổi giá trị này và nó được sử dụng trong suốt ứng dụng của tôi. Cảm ơn.

Đây là những gì tôi đang cố gắng ... suy nghĩ?

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 

Trả lời

39

Đừng như sau:

  1. đổi tên cột A
  2. tạo cột B mới như ngày
  3. di chuyển dữ liệu từ A đến B
  4. loại bỏ Một

Nói cách khác

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 cho #reset_column_information, mà tôi chưa bao giờ thấy trước đây. Có vẻ như nó sẽ rất tiện dụng trong những lần rất hiếm khi cần thiết. – jdl

+0

ditto re: đặt lại. – Angela

+1

Vẫn hoạt động sau hai năm! –

1

Đây là một phiên bản sửa đổi và thử nghiệm các giải pháp Simone Carletti của

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

Mặc dù vậy, bạn vẫn muốn có 'find_each'. Phiên bản của bạn sẽ đọc toàn bộ bảng vào bộ nhớ, trong khi find_each sẽ nhận được một số hàng tại thời điểm đó. – clacke

Các vấn đề liên quan