2010-06-19 9 views
20

Próbuję rake db: migracje do mojej instancji heorku i pojawia się błąd. Najczęściej zadawane pytania opisują mój błąd poniżej:Jak zmienić typ kolumny w 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.

Jak zmienić tę migrację teraz. To jest problem, który mam. Dla moich kontaktów tabeli, stworzyłem następujące:

t.string :date_entered 

W późniejszej migracji, mam następujące:

change_column :contacts, :date_entered, :date 

Ten change_column wydaje się być problemem.

Czy powinienem ... zmienić ręcznie tę migrację? Czy istnieje sposób, w jaki mogę wyczyścić dane w moich tabelach (nie wiedziałem, że Heroku rozpozna dane w tabeli, ponieważ robię prowizję).

Oczywiście muszę zmienić tę wartość i jest ona używana w całej mojej aplikacji. Dzięki.

Oto, co próbuję ... myśli?

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 

Odpowiedz

39

Wykonaj następujące czynności:

  1. zmienić nazwę kolumna A
  2. utworzyć nową kolumnę B jako daty
  3. przenieść dane z A do B
  4. usunąć

Innymi słowy

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 dla #reset_column_information, który nigdy wcześniej nie widział. Wygląda na to, że byłby przydatny w tych bardzo rzadkich chwilach, kiedy jest potrzebny. – jdl

+0

ditto re: reset. – Angela

+1

Nadal działa ponad dwa lata później! –

1

Jest to zmodyfikowana wersja i przetestowane rozwiązania Simone 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

Chcesz tego 'find_each' chociaż. Twoja wersja odczyta całą tabelę do pamięci, podczas gdy find_each dostanie pewną liczbę wierszy w tym czasie. – clacke

Powiązane problemy