【问题标题】:Empty string as default value for enum type column instead of nil in Rails空字符串作为枚举类型列的默认值,而不是 Rails 中的 nil
【发布时间】:2015-04-09 20:37:40
【问题描述】:

问题是我收到空字符串而不是 nil 作为 PostgreSQL 数据库中 enum 列的默认值,同时创建新的 ActiveRecord 对象。这是更多信息。

我的迁移:

class CreateTickets < ActiveRecord::Migration
  def change
    execute <<-SQL
      CREATE TYPE ticket_status AS ENUM ('submitted', 'open', 'closed');
    SQL

    create_table :tickets do |t|
      t.string :name
      t.column :status, :ticket_status

      t.timestamps null: false
    end
  end
end

我的模特:

class Ticket < ActiveRecord::Base
  STATUS = {
    submitted:  'submitted',
    open:       'open',
    closed:     'closed'
  }

  validates :status, inclusion: { in: Ticket::STATUS.values }, allow_nil: true
end

我的目标是在数据库表中允许 nil 值,但是当我尝试创建新对象时,我收到“未包含在列表中的错误”:

2.2.0 :005 >   Ticket.create!
   (0.8ms)  BEGIN
   (0.5ms)  ROLLBACK
ActiveRecord::RecordInvalid: Validation failed: Status is not included in the list 

这是因为创建新对象时使用空字符串作为状态列中的默认值,而其他列得到正确的 nil 值:

2.2.0 :010 >   Ticket.new
 => #<Ticket id: nil, name: nil, status: "", created_at: nil, updated_at: nil> 

这里还有一个条件,我确实想使用原生 PostgreSQL ENUM 类型,而不是整数映射。

【问题讨论】:

  • 尝试使用t.column :status, :ticket_status, default: nil设置默认值

标签: ruby-on-rails postgresql validation activerecord enums


【解决方案1】:

有一个allow_blank 选项。

validates :status, inclusion: { in: Ticket::STATUS.values }, allow_blank: true

http://edgeguides.rubyonrails.org/active_record_validations.html#allow-blank

更新:为此,您应该在枚举中添加空字符串:

CREATE TYPE ticket_status AS ENUM ('', 'submitted', 'open', 'closed');

【讨论】:

  • 但是对于ticket_status 类型的列,空字符串不是有效值,因此验证会通过,但数据库会引发异常。在这种情况下,更改验证选项只是移动错误。
  • 是的,你是对的,但是可以将空字符串添加到数据库枚举中。我会相应地更新我的答案。
  • 谢谢! allow_blank 选项成功了,但在 ActiveRecord 类中的某个地方还有更多魔力。我刚刚按照您的建议更改了验证规则,瞧!对象仍然包含“”作为值,但它在数据库中保存为NULL。对我来说仍然看起来有点奇怪,但至少我在 ENUM 定义中没有多余的价值。
猜你喜欢
  • 2015-10-12
  • 2012-12-29
  • 1970-01-01
  • 2016-06-13
  • 1970-01-01
  • 2016-05-08
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多