自定义验证布尔字段具有布尔值而不是任何其他类型

时间:2015-07-09 11:07:54

标签: ruby-on-rails

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

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

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

2 个答案:

答案 0 :(得分:1)

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

validate :check_boolean_field

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

答案 1 :(得分:1)

每次为属性赋值时,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