【问题标题】:Rails database defaults and model validation for boolean fieldsRails 数据库默认值和布尔字段的模型验证
【发布时间】:2012-05-08 21:11:41
【问题描述】:

在 Rails 模型中,我有一个属性 is_subscriber,当我构造一个 db 迁移以将此列添加到数据库时,我指定默认值为 false:

t.boolean  "is_subscriber",   :default => false

我还在模型中指定了这个属性需要存在:

validates :is_subscriber, presence: true

那么为什么我在创建模型实例时没有指定这个属性会出现这个错误呢?

2012-05-08T21:05:54+00:00 app[web.1]: ActiveRecord::RecordInvalid (Validation failed: Is subscriber can't be blank):

【问题讨论】:

    标签: ruby-on-rails activerecord ruby-on-rails-3.2


    【解决方案1】:

    来自here

    如果您想验证是否存在布尔字段(其中 真实值是真假),你会想要使用 validates_inclusion_of :field_name, :in => [true, false] 这是由于 以 Object#blank 的方式?处理布尔值。假的空白? # => 真的

    或者在 Rails3 中

    validates :field, :inclusion => {:in => [true, false]}
    

    【讨论】:

    • 好点(投票赞成),但我认为数据库规则不会导致在这种情况下成功验证,对吧?
    • @SteveRowley 为什么不呢? Rails 处理类型之间的数据转换,所以它就像一个魅力。请记住,迁移语法也会转换为 db 语法。
    • 我认为不是类型转换问题。不会是时间问题吧?您创建一个新对象,不为某事指定值,调用.save,然后运行验证。如果它们没有引发错误,则会在数据库中插入一条记录,如果您遗漏的值为空白,则数据库会使用迁移中指定的默认值创建记录。我看到的问题是,因为验证是在插入记录之前运行的,所以验证应该失败,因为数据库从来没有机会将该字段的值设置为任何值。不过听起来我错了。嗯。
    • 终于能够对此进行测试 - 看起来该属性在创建对象时设置为迁移默认值。好用!
    • @SteveRowley 你错过了两件事。首先save 强制验证,因此除非您将:validate => false 选项提供给保存,否则您将无法保存无效记录,因此如果您指定 :inclusion 验证器,您将无法保存空白记录(无!=错误的)。其次,当您在 db 架构中指定默认值时,如果在创建时未提供这些值,则任何活动记录实例都将使用这些值进行初始化,因此在此示例中 Model.new.is_subscriber 为 false 而不是 nil。
    【解决方案2】:

    我已经解决了这个问题:

    validates_presence_of :is_subscriber, :if => 'is_subscriber.nil?'
    

    【讨论】:

      【解决方案3】:

      我认为将其包装在自定义验证器中会更整洁。

      /app/validators/is_boolean_validator.rb

      class IsBooleanValidator < ActiveModel::EachValidator
        def validate_each(record, attribute, parameters)
          if !parameters.in? [true,false]
            record.errors[attribute] << 'This must be true or false.'
          end
        end
      end
      

      那么您必须通过将以下内容添加到 /config/application.rb 来确保已加载

      config.autoload_paths += %W["#{config.root}/app/validators/"]
      

      (不要忘记重新启动服务器以加载此内容)

      然后您可以更整洁地验证

      validates: :field1, field2, is_boolean: true
      

      【讨论】:

        【解决方案4】:
        validates :column_name, :inclusion => {:in => [true, false]}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-03
          • 1970-01-01
          • 1970-01-01
          • 2011-05-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多