我对模型的属性进行了以下验证:
validates :on_ride_photo,
presence: true,
inclusion: { in: [true, false] }
然后我进行了以下测试:
context 'on_ride_photo' do
it { should validate_presence_of(:on_ride_photo) }
it { should allow_value(true).for(:on_ride_photo) }
it { should allow_value(false).for(:on_ride_photo) }
it { should_not allow_value(nil).for(:on_ride_photo) }
it { should_not allow_value(4).for(:on_ride_photo) }
it { should_not allow_value('yes').for(:on_ride_photo) }
end
但是在运行我的规范时出现以下错误:
2) Coaster validations should allow on_ride_photo to be set to false
Failure/Error: it { should allow_value(false).for(:on_ride_photo) }
Did not expect errors when on_ride_photo is set to false, got error:
# ./spec/models/coaster_spec.rb:86:in `block (3 levels) in <top (required)>'
我是否希望允许false作为有效值被它必须存在的事实所击倒而且false被归类为不存在?如果是这样,那么我该如何解决这个问题?
答案 0 :(得分:2)
是的,问题出在presence: true
,它会检查该属性不是Object#blank?
。由于验证是附加的,inclusion:
子句无法“覆盖”false
未通过presence
测试的事实。
以下内容来自http://edgeguides.rubyonrails.org/active_record_validations.html#presence:
由于
的布尔字段false.blank?
为true
,因此您需要验证状态 您应该使用validates :field_name, inclusion: { in: [true, false] }.
有关如何处理布尔字段的讨论,请参阅Billy Chan's answer,特别包括有关哪些值被视为nil
,true
和false
的信息。
答案 1 :(得分:1)
最后,我得到了答案,感谢彼得的更新。
t.boolean :foo
true
或false
值,请参阅下文。 (我认为没有必要对它们进行单元测试,虽然集成或功能测试可以包含部分内容,但 我只是浏览了源代码。 boolean类型,PostgreSQL,Sqlite3或MySQL最终将指向ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
,
# convert something to a boolean
def value_to_boolean(value)
if value.is_a?(String) && value.empty?
nil
else
TRUE_VALUES.include?(value)
end
end
然后通过这个常数来判断
# the namespace is still "ActiveRecord::ConnectionAdapters::Column"
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set
所以,我们终于明白了。
如果为空,则为
如果不为空,请检查它是否为TRUE_VALUE,否则为false。这就是为什么“4”,“是”是错误的。