Rails:validation包含布尔失败测试
我试图确保我的模型的一个字段是一个布尔值,但我的测试继续失败。
阅读本文后: validationRspec和Rails中的布尔值以及此Rails:如何validation某些内容是否为布尔值? 我最终这样做:
class Model { :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
我错过了什么? 似乎价值是以某种逻辑方式转换但是在哪里以及如何防止它? 如何正确地进行这种validation?
我不知道你需要将这个想法validation一个布尔字段为真/假来自哪里,但我最近在一些不相关的项目中看到了它,所以我开始怀疑这不是一个模因从某处开始。
它是一个布尔字段,它必须是真或假。 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 => [true, false]
因此模型有效。 出于同样的原因,“假”和“123”失败。 “true”是布尔值true的可接受值,因此该字段设置为true,并且由于上述原因仍然有效。
我不是Rails大师,但我会把我的脖子伸到这里说你绝对想要validation布尔值:inclusion => { :in => [true, false] }
– 也就是假设你做的不想允许nil(NULL)值。
来自数据库编程背景,我已经学会记住布尔字段可以有三个值:true,false和NULL。 在本机SQL中编程时,NULL需要特殊处理( is null
而不是= null
),这会导致大量额外工作。
在今天使用Rails 3.2进行测试时,创建一个带有nil值的未经validation的布尔字段并将其保存到我的PostgreSQL数据库是没有问题的,它将其尽职地存储为NULL。 为了避免可能导致的所有问题,我打算在Rails中使用这种方法来处理布尔值:
- 在迁移中使用
:null => false
定义布尔字段。 - 使用
:inclusion => { :in => [true, false] }
来validation模型中的字段。 如果字段未初始化(nil),这会给出一个很好的消息。
一开始并不直观,我不能使用:presence
validation,但事实certificate:presence
validation值不是空白,值false
为空。 换句话说,如果validation:presence => true
并将值设置为false
,则validation将失败。 请参阅API中的validates_presence_of和@Paul A Jungwirth对@ Karmajunkie的回答的评论。