【问题标题】:Rails: Validating inclusion of a boolean fails testsRails:验证是否包含布尔值失败测试
【发布时间】:2011-07-07 09:37:29
【问题描述】:

我正在尝试确保我的模型的字段是布尔值,但我的测试一直失败。

读完这个:Validating boolean value in Rspec and Rails 和这个Rails: how do I validate that something is a boolean? 我最终是这样做的:

class Model < ActiveRecord::Base

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

end

我尝试了几种不同的方法(使用 rspec 和 shoulda 匹配器)来测试它,但由于我的测试不断失败,我现在只能采用最愚蠢的 (?) 方法。尽管如此,测试没有通过,我猜有某种机制可以在某处转换值。

这是我用来了解发生了什么的:

# create instance without setting value ...

# these work as expected
model_instance.valid?.should be_false      # passes
model_instance.my_field = true
model_instance.valid?.should be_true       # passes
model_instance.my_field = false       
model_instance.valid?.should be_true       # passes

# works as expected
model_instance.my_field = ""
model_instance.valid?.should be_false      # passes

# these should pass but fail
model_instance.my_field = "foo"
model_instance.my_field.should == "foo"    # fails as well, my_field == false
model_instance.valid?.should be_false      # fails

model_instance.my_field = "false"
model_instance.my_field.should == "false"  # fails as well, my_field == false
model_instance.valid?.should be_false      # fails

model_instance.my_field = "123"
model_instance.valid?.should be_false      # fails

model_instance.my_field = "true"
model_instance.my_field.should == "true"   # fails as well, my_field == true
model_instance.valid?.should be_false      # fails

我错过了什么? 似乎该值以某种合乎逻辑的方式转换,但在哪里以及如何防止它?如何正确进行这种验证?

【问题讨论】:

    标签: ruby-on-rails unit-testing validation boolean


    【解决方案1】:

    我不知道您需要将布尔字段验证为真/假的想法来自哪里,但我最近在一些不相关的项目中看到了它,所以我开始怀疑这是否不是一个从某个地方开始的模因。

    它是一个布尔字段,它必须为真或假。 AR 为您处理布尔值的实现细节。如果您想要一个布尔字段,请在数据库中创建一个布尔字段。故事结局。

    查看源代码,这是将值转换为布尔值的代码:

    # File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 147
    147:         def value_to_boolean(value)
    148:           if value.is_a?(String) && value.blank?
    149:             nil
    150:           else
    151:             TRUE_VALUES.include?(value)
    152:           end
    153:         end
    

    以下是相当于布尔值的值:

    TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
    FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
    

    所以再看看你上面的代码,一切都应该是这样,除了你所期望的不正确。将“foo”分配给一个布尔值,我们看到“foo”不在可接受的真值列表中,所以布尔字段默认为 false,这就是它稍后将从其访问器返回的值。该字段的布尔值仍为:in =&gt; [true, false],因此模型有效。 “false”和“123”因同样的原因而失败。 “true”是布尔值 true 的可接受值,因此该字段设置为 true,并且由于上述原因仍然有效。

    【讨论】:

    • 谢谢,我不知道 FALSE_VALUES / TRUE_VALUES 常量。你的综合回答很好地解释了它!今天学到了一些东西。
    • 我认为模因是当布尔字段具有 validates_presence_of 时,只要它为假,它就会失败验证。解决方法是使用 validates_inclusion_in。我自己在 Rails 3.0.9 中看到了这种行为。见这里:ruby-forum.com/topic/99285
    • 我再次阅读了有关验证的 Rails 指南,它解释了如何验证布尔字段。我的第一直觉是“我为什么要验证一个布尔值,因为它永远是真或假,永远不会为零?”。试图找到我碰到这篇文章的原因。我认为模因是从新手那里开始的,而且有点卡住了。 “如果他们解释如何,应该这样做”。我认为这是为了完整起见而解释的......只是我的 2 美分价值......
    • 思路是防止字段被nil
    • TRUE_VALUES 已在 Rails v5 中删除。查看新代码:github.com/rails/rails/commit/…
    【解决方案2】:

    我不是 Rails 专家,但我会在这里直言不讳地说你绝对想要验证 :inclusion =&gt; { :in =&gt; [true, false] } 的布尔值——也就是说,假设你不想允许 nil (NULL) 值.

    来自数据库编程背景,我学会了记住布尔字段可以有三个值:true、false 和 NULL。在本机 SQL 中编程时,NULL 需要特殊处理(is null 而不是 = null),这会导致大量额外工作。

    今天在使用 Rails 3.2 进行测试时,创建一个具有 nil 值的未经验证的布尔字段并将其保存到我的 PostgreSQL 数据库中,它被忠实地存储为 NULL 是没有问题的。为了避免所有可能导致的问题,我计划在 Rails 中将这种方法用于布尔值:

    • 在迁移中使用 :null =&gt; false 定义布尔字段。
    • 使用:inclusion =&gt; { :in =&gt; [true, false] } 验证模型中的字段。如果该字段未初始化 (nil),这会给出一个很好的消息。

    一开始我不能使用:presence 验证并不直观,但事实证明:presence 验证该值不为空,而值false 为空.换句话说,如果您验证:presence =&gt; true 并将值设置为false,则验证将失败。请参阅 API 中的 validates_presence_of 和 @Paul A Jungwirth 对 @Karmajunkie 答案的评论。

    【讨论】:

    • 我完全同意。我从不希望 INSERT 被数据库拒绝(非常丑陋的消息,通常是 500 错误),因为它可以被 Rails 验证捕获,并带有用户友好的有用错误消息。
    • 抱歉,我的 model.rb 文件无法使用语法。我尝试了 validates 的变体:property_name、inclusion (true, false) 以及 :inclusion => { in => [true,false] }。你的答案是在 model.rb 文件中使用吗?
    • @flobacca,是的,它在模型中,就像在原始问题顶部的示例中一样。如果它不适合您,您可能需要创建自己的问题,以便显示特定的代码示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多