为什么我必须为shoulda匹配器包含显式nilify空白:`验证通过?

时间:2017-05-29 04:21:53

标签: ruby-on-rails activerecord shoulda

我的数据库中有一个包含时区的字符串列。有效值包括nil或ActiveSupport识别为时区的任何内容

我使用shoulda-matchers为我的模型验证编写规范:

# app/models/my_model.rb
class MyModel < ApplicationRecord
  validates :timezone, inclusion: ActiveSupport::TimeZone::MAPPING.keys, allow_nil: true
end

# spec/models/my_model_spec.rb
describe "timezone" do
  it do 
    should validate_inclusion_of(:timezone).
      in_array(ActiveSupport::TimeZone::MAPPING.keys).
      allow_blank
    end
end

它引发了一个错误:

Failure/Error: it { should validate_inclusion_of(:timezone).in_array(ActiveSupport::TimeZone::MAPPING.keys).allow_blank }

     MyModel did not properly validate that
     :timezone is either ‹"International Date Line West"›, ‹"Midway Island"›,
     ‹"American Samoa"›, ‹"Hawaii"›, ‹"Alaska"›, ‹"Pacific Time (US &
     .....
     .....
     .....
     ‹"Auckland"›, ‹"Wellington"›, ‹"Nuku'alofa"›, ‹"Tokelau Is."›, ‹"Chatham
     Is."›, or ‹"Samoa"›, but only if it is not blank.
       After setting :timezone to ‹""›, the matcher expected the
       MyModel to be valid, but it was invalid
       instead, producing these validation errors:

       * timezone: ["is not included in the list"]

是否匹配器将列设置为""并期望验证通过。但为什么会这样呢?严格允许nil,但空字符串值不应该是,对吧?

有没有更合适的方法来设置我错过了?

要解决它,我使用了before_validation块。 (我知道nilify_blanks gem做同样的事情)。但奇怪的是,我必须将其包括在内

before_validation do
  self[:timezone] = nil if self[:timezone].blank?
end

1 个答案:

答案 0 :(得分:2)

.blank?是一个ActiveSupport方法,对nilfalse以及更为无效的""(空字符串)返回true。

这就是allow_blank使用空字符串进行测试的原因。请改用allow_nil

# spec/models/my_model_spec.rb
describe "timezone" do
  it do 
    should validate_inclusion_of(:timezone).
      in_array(ActiveSupport::TimeZone::MAPPING.keys).
      allow_nil
  end
end