Rails:验证包含布尔失败测试

pol*_*lau 15 validation unit-testing boolean ruby-on-rails

我试图确保我的模型的一个字段是一个布尔值,但我的测试仍然失败.

阅读本文后:验证Rspec和Rails中的布尔值以及此Rails:如何验证某些内容是否为布尔值?我最终这样做了:

class Model < ActiveRecord::Base

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

end
Run Code Online (Sandbox Code Playgroud)

我已经尝试过几种不同的测试方法(使用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
Run Code Online (Sandbox Code Playgroud)

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

kar*_*kie 39

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

它是一个布尔字段,它必须是真或假.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
Run Code Online (Sandbox Code Playgroud)

这里的值等于它们的布尔值对应物:

TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
Run Code Online (Sandbox Code Playgroud)

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

  • 这个想法是为了防止这个领域变成"零". (9认同)
  • 我认为模因是当一个布尔字段有validates_presence_of时,只要它是假的,它就会失败验证.解决方法是使用validates_inclusion_in.我在Rails 3.0.9中看到了这种行为.见这里:http://www.ruby-forum.com/topic/99285 (8认同)

Mar*_*rry 28

我不是Rails大师但是我会把我的脖子伸到这里然后说你绝对想要验证布尔值:inclusion => { :in => [true, false] }- 也就是说,假设你不想允许nil(NULL)值.

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

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

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

这不是第一次,我不能用一个直观的:presence验证,但事实证明,:presence验证该值不为空,该值false 空白.换句话说,如果验证:presence => true并将值设置为false,则验证将失败.请参阅API中的validates_presence_of和@Paul A Jungwirth对@ Karmajunkie的回答的评论.