【问题标题】:Custom validation that boolean field has a boolean and not any other type布尔字段具有布尔值而不是任何其他类型的自定义验证
【发布时间】:2015-09-27 17:16:07
【问题描述】:

目前,我的模型和验证是这样的:

class Suya < ActiveRecord::Base
  belongs_to :vendor

  validates :meat, presence: true
  validates_inclusion_of :spicy, :in => [true, false]
end

问题是当我运行这个测试时:

test "suya is invalid if spiciness is not a boolean" do
    suya = Suya.new(meat: "beef", spicy: 1)
    suya1 = Suya.new(meat: "beef", spicy: "some string")

    assert suya.invalid?
    refute suya1.valid?
  end

我收到一条弃用警告:

弃用警告:您尝试分配的值不是 将 truefalse 显式添加到布尔列。目前这个值 转换为false。这将改变以匹配 Ruby 的语义,并将 在 Rails 5 中转换为 true

所以我认为我的验证没有做我认为应该做的事情。我认为我的验证检查列值的存在以及它是否是或转换为真或假。所以我认为我的测试装置都转换为假,因此通过了我不想要的测试。我能做什么?

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    您可以使用自定义验证,例如:

    validate :check_boolean_field
    
    def check_boolean_field
      false unless self.spicy.is_a?(Boolean)
    end
    

    【讨论】:

    • Ruby 中没有Boolean
    【解决方案2】:

    Rails 会在您为属性赋值时执行类型转换。这是一个方便的事情。这不是您的文本案例的错,而是 Rails 的工作方式。如果属性是布尔值,它将转换看起来像真的值(true1'1''t''T''true''TRUE''on''ON' ) 到true 和其他任何到false。例如:

    suya.spicy = "asdf"
    suya.spicy # => false
    
    # Likewise for other attribute types:
    # Assuming Suya has an `id` attribute that is an Integer
    suya.id = "asdf"
    suya.id # => 0  # Because "asdf".to_i # => 0
    
    # Assuming Suya has a `name` attribute that is a String
    suya.name = 1
    suya.name # => "1"  # Because 1.to_s # => "1"
    

    这就是 rails 的工作原理。在您的测试用例中,您的值通过批量赋值被类型转换为它们各自的属性类型。

    您可以通过为布尔值分配“一些值”来测试 Rails 的类型转换,也可以在测试用例中使用更明显的布尔值,例如 truefalse

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 2016-03-08
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      相关资源
      最近更新 更多