【问题标题】:Rails 3 migration now fail in rails 5Rails 3 迁移现在在 Rails 5 中失败
【发布时间】:2018-05-04 18:54:24
【问题描述】:

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

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'

我尝试了很多方法来解决这个问题。但没有任何效果。

谁能帮帮我

谢谢

【问题讨论】:

  • 我已尝试在错误消息中添加他们建议的内容,但出现语法错误。我不知道什么是好的。
  • 如果要将 resource_week_day_starts 声明为数组(字符串数据类型)列,则迁移应为 change_column :resource_week_day_starts, :wday, :string, array: true
  • wday 列现在是什么类型? integer?并且您想将其更改为字符串数组(即varchar[]character varying[])?
  • @muistooshort 是的,它现在是一个整数,我们想转换为不同的字符...

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


【解决方案1】:

你有三个问题:

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

(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)'

如果您当前有nulls inwday,这可能会在wday 中留下array[null] 值。如有必要,您可以在之后清理它们。

【讨论】:

  • 似乎这不是解决方案...在旧服务器上,该列的类型为:字符变化 DEFAULT '--- []'::character 变化并且在新闻服务器上它是类型character varying[] DEFAULT '{}'::character varying[] 并且我无法将数据从旧服务器导入到新服务器。我怎么能在字符 varing[] 上得到字符 varaying
  • DEFAULT '--- []'::character varying 看起来像是某种 YAML 进入了列定义。 character varying[] 是一个字符串数组,'{}'::character varying[] 是 PostgreSQL 中的一个空数组字面量,所以没关系。我不确定问题是什么。您想迁移到单个字符串而不是字符串数组吗?旧列实际上不是整数?你有奇怪的数据吗?
  • 是的,事实上我想在新数据库中拥有完全相同类型的列。当迁移创建并运行时,我们在 rails 3 下,迁移创建了一个 DEFAULT '--- []'::character 变化。所以我需要让我的迁移创建一个列,就像我们在 rails 3 下一样。是的,该列的实际内容是一种 yml。
  • 那为什么不把默认设置为'--- []'呢?但实际上,如果你使用的是 PostgreSQL,你最好使用真正的数组而不是一些 serialize 混乱。
猜你喜欢
  • 1970-01-01
  • 2011-10-31
  • 1970-01-01
  • 2010-10-15
  • 2021-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多