Ошибка миграции Rails с Postgres при нажатии на Heroku

Я пытаюсь выполнить следующую миграцию, чтобы изменить столбец "число" в таблице моделей "tweet"

class ChangeDataTypeForTweetsNumber < ActiveRecord::Migration
  def up
    change_column :tweets do |t|
      t.change :number, :integer
    end
  end

  def down
    change_table :tweets do |t|
      t.change :number, :string
    end
  end
end

После выполнения следующей миграции в герою....

heroku rake db:migrate:up VERSION=20120925211232

Я получаю следующую ошибку

    PG::Error: ERROR:  column "number" cannot be cast to type integer
: ALTER TABLE "tweets" ALTER COLUMN "number" TYPE integer

Любые мысли, которые у вас есть, будут очень оценены.

Спасибо всем.

Ответ 1

Из точное руководство:

[ALTER TABLE... ALTER COLUMN...]
Необязательное предложение USING указывает, как вычислить новое значение столбца из старого; если опустить, преобразование по умолчанию такое же, как присваивание от старого типа данных к новому. Предложение USING должно быть предоставлено, если нет неявного или присваиваемого приведения от старого к новому типу.

В PostgreSQL нет неявного преобразования от varchar до int, поэтому он жалуется, что column "number" cannot be cast to type integer и ALTER TABLE не работают. Вы должны сообщить PostgreSQL, как преобразовать старые строки в числа, чтобы они соответствовали новому типу столбцов, а это значит, что вам нужно получить предложение USING в свой ALTER TABLE. Я не знаю, как сделать Rails для этого, но вы можете сделать это вручную достаточно легко:

def up
  connection.execute(%q{
    alter table tweets
    alter column number
    type integer using cast(number as integer)
  })
end

Вы хотите следить за значениями, которые нельзя отличить от целых чисел, PostgreSQL сообщит вам, есть ли проблемы, и вам придется исправить их до того, как миграция будет успешной.

Ваша текущая миграция должна быть прекрасной, преобразование integer в varchar должно выполняться автоматически.

Ответ 2

То же, что и выше, но немного более кратким:

change_column :yourtable, :column_to_change, 'integer USING CAST("column_to_change" AS integer)'