Миграция Rails 3 теперь терпит неудачу в rails 5 - PullRequest
0 голосов
/ 04 мая 2018

У меня есть эта миграция, где я преобразовываю столбец из целого числа в массив строк.

class ChangeWdayFromIntegerToStringInResourceWeekDayStart < ActiveRecord::Migration[4.2]
  def up
    change_column :resource_week_day_starts, :wday, :string, default: []
    add_column :resource_week_day_starts, :number_days, :integer, default: 7
  end

  def down
    change_column :resource_week_day_starts, :wday, :string, default: nil
    change_column :resource_week_day_starts, :wday, 'integer USING CAST(wday AS integer)'
    remove_column :resource_week_day_starts, :number_days
  end
end

Эта миграция работает очень хорошо, когда мы находимся в рельсах 3, но у нас есть миграция на рельсы 5, и теперь мы пытаемся настроить новый сервер. При запуске миграции в rails 5 мы получили это сообщение об ошибке:

PG::DatatypeMismatch: ERROR:  column "wday" cannot be cast automatically to type character varying[]
HINT:  You might need to specify "USING wday::character varying[]".
: ALTER TABLE "resource_week_day_starts" ALTER COLUMN "wday" TYPE character varying[]
/home/ruby/src/mapsbooking/db/migrate/20170307000000_change_wday_from_integer_to_string_in_resource_week_day_start.rb:3:in `up'

Я пробовал много способов исправить это. Но ничего не работает.

Может ли кто-нибудь мне помочь

Спасибо

1 Ответ

0 голосов
/ 04 мая 2018

У вас есть три проблемы:

  1. Как сказано в комментариях max , вам нужно включить в параметры array: true, чтобы получить столбец массива.
  2. Вам нужно выражение SQL для преобразования одного целого числа в массив строк, чтобы вы могли включить подходящее предложение USING в ALTER TABLE.
  3. change_column хочет изменить тип и значение по умолчанию отдельно.

(1) легко, добавьте array: true к change_column опциям.

(2) немного сложнее, но на ум приходят несколько вариантов. Вы можете использовать оператор объединения элементов в массив и приведение типа:

wday::varchar || array[]::varchar[]

:: - приведение типа, || - оператор конкатенации, а array[] - пустой массив. Или, если это слишком много знаков препинания, вы можете использовать функцию array_append, чтобы сделать то же самое:

array_append(array[]::varchar[], wday::varchar)

(3) можно решить, отбросив прежнее значение по умолчанию с помощью вызова change_column_default перед change_column.

Соединяя их вместе:

change_column_default :resource_week_day_starts, :wday, nil
change_column :resource_week_day_starts,
              :wday,
              :string,
              array: true,
              default: [],
              using: 'array_append(array[]::varchar[], wday::varchar)'

Это может оставить вас с array[null] значениями в wday, если у вас есть nulls in wday`. Вы можете очистить их после необходимости.

...