Rails 3迁移现在在rails 5中失败

时间:2018-05-04 18:54:24

标签: ruby-on-rails postgresql ruby-on-rails-5 rails-migrations

我有这种迁移,我将列从整数转换为字符串数组。

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

当我们在rails 3中时,这种迁移非常有效,但是我们已经迁移到rails 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 :(得分:2)

你有三个问题:

  1. 正如max在评论中所说,您需要在选项中包含array: true,以便获得数组列。
  2. 您需要一个SQL表达式将单个整数转换为字符串数组,以便您可以在ALTER TABLE中包含合适的USING子句。
  3. change_column想要分别更改类型和默认值。
  4. (1)很简单,将array: true添加到change_column选项中。

    (2)稍微困难但想到几个选项。您可以使用element-to-array concatenation operator和类型转换:

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

    ::是类型转换,||是连接运算符,array[]是空数组。或者,如果这是太多标点符号,您可以使用array_append函数执行相同的操作:

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

    (3)可以通过在change_column之前调用change_column_default来删除旧默认值来处理。

    将它们放在一起:

    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`,这可能会在wday中留下nulls in个值。如有必要,你可以清理它们。