尝试更新Postgres ENUM列的值会引发以下异常:
ActiveRecord :: StatementInvalid异常:PG :: DatatypeMismatch:错误:列“interesting_column”的类型为interesting_thing但表达式的类型为整数
第1行:更新“interesting_table”SET“interesting_column”= 0,“updated_a ...
提示:您需要重写或转换表达式。
InterestingTable.first.update_attributes!(normal_column: 'food')
# => perfectly fine
InterestingTable.first.update_attributes!(interesting_column: 'foo')
# => above exception
以下是创建表的迁移:
class CreateInterestingTables < ActiveRecord::Migration
def up
execute <<-SQL
CREATE TYPE normal_thing AS ENUM ('food', 'water', 'shelter');
CREATE TYPE interesting_thing AS ENUM ('foo', 'bar', 'baz');
SQL
create_table :interesting_tables do |t|
t.column :normal_column, :normal_thing
t.column :interesting_column, :interesting_thing
end
end
def down
drop_table :interesting_tables
execute 'DROP TYPE normal_thing'
execute 'DROP TYPE interesting_thing'
end
end
答案 0 :(得分:3)
问题是,当列在数据库中具有正确的类型时,活动记录将尝试将其解释为integer
。您可以通过运行验证:
InterestingTable.columns
# => [#<ActiveRecord::ConnectionAdapters::PostgreSQLColumn:0x007f7567f82260
# @coder=nil,
# @default=nil,
# @limit=nil,
# @name="id",
# @null=false,
# @precision=nil,
# @primary=true,
# @scale=nil,
# @sql_type="integer",
# @type=:integer>,
# #<ActiveRecord::ConnectionAdapters::PostgreSQLColumn:0x007f7568075690
# @coder=nil,
# @default=nil,
# @limit=nil,
# @name="normal_column",
# @null=true,
# @precision=nil,
# @primary=false,
# @scale=nil,
# @sql_type="normal_thing",
# @type=nil>,
# #<ActiveRecord::ConnectionAdapters::PostgreSQLColumn:0x007f7568075668
# @coder=nil,
# @default=nil,
# @limit=nil,
# @name="interesting_column",
# @null=true,
# @precision=nil,
# @primary=false,
# @scale=nil,
# @sql_type="interesting_thing",
# @type=:integer>]
请注意第二列的类型是nil
,而最后一列的类型是integer
。如果您的字符串没有以数字开头,则String#to_i
会返回0
,因此您会收到您尝试分配0
的错误。
但为什么呢?原因 - interesting_thing
包含子字符串int
,适配器认为它是integer
。这似乎是一个长期存在的错误,直到rails 4.2之前还没有修复。 The offending method.
可能的解决方案: