Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 使用shoulda匹配器结合“惟一性”和“范围”测试“allow_nil”`_Ruby On Rails_Activerecord_Shoulda - Fatal编程技术网

Ruby on rails 使用shoulda匹配器结合“惟一性”和“范围”测试“allow_nil”`

Ruby on rails 使用shoulda匹配器结合“惟一性”和“范围”测试“allow_nil”`,ruby-on-rails,activerecord,shoulda,Ruby On Rails,Activerecord,Shoulda,我正在为存储键/值对的表构建ActiveRecord模型 范例- |------------------------------| | KEY | VALUE | |----------|-------------------| | LOCATION | San Francisco, CA | | TITLE | Manager | | LOCATION | New York City, NY | |------------------

我正在为存储键/值对的表构建ActiveRecord模型

范例-

|------------------------------|
| KEY      | VALUE             |
|----------|-------------------|
| LOCATION | San Francisco, CA |
| TITLE    | Manager           |
| LOCATION | New York City, NY |
|------------------------------|
这是模型-

class CompanyEnum < ActiveRecord::Base
  KEYS = [:title, :department, :location]
  KEYS_ENUM = KEYS.map(&:to_s).map(&:upcase)

  # `key` column must be one of the above - LOCATION, DEPARTMENT, or TITLE
  validates(:key, inclusion: KEYS_ENUM, allow_nil: false)

  # `value` can be anything, but must be unique for a given key (ignoring case) 
  validates(
    :value,
    uniqueness: { scope: :key, case_sensitive: false },
    allow_nil: false
  )
end
我的问题是
:key
的第一次验证通过,但是
:value
的第二次验证失败。根据模型定义,两者都使用相同的
allow\u nil:false
选项

1) CompanyEnum validations value should not allow value to be set to nil
   Failure/Error: it { should_not allow_value(nil).for(:value) }
     Expected errors when value is set to nil,
     got no errors
   # ./spec/models/company_enum_spec.rb:13:in `block (4 levels) in <top (required)>'
   # ./spec/support/analytics.rb:4:in `block (2 levels) in <top (required)>'
1)CompanyEnum validations值不应允许将该值设置为nil
失败/错误:它{should_not allow_value(nil).for(:value)}
值设置为nil时的预期错误,
没有错误
#./spec/models/company_enum_spec.rb:13:in'block(4层)in'
#./spec/support/analytics.rb:4:in'block(2级)in'
allow\u nil:false
唯一性:
范围:
optoins一起使用是否存在逻辑问题?或者它与我命名实际列
:key
:value
有什么关系(因为它们看起来很通用,足以与其他方法冲突)


谢谢

allow\u nil:false
唯一性验证并不意味着
nil
不是允许的值。这有点误导

您可能已经知道,默认情况下,唯一性验证是这样工作的(根据您使用的代码判断):

  • 如果有两条记录具有相同的
    ,则第二条记录与第一条记录相比应无效(前提是第一条记录存在于数据库中)
  • 如果有两条记录具有不同的
    ,则这两条记录都应有效
那么
允许\u nil
做什么呢?让我们看看你要说什么:

:allow_nil
-如果设置为
true
,则在属性为
nil
(默认值为
false
)时跳过此验证

因此,如果为true,
allow_nil
允许两条记录与正在验证的属性的
nil
值共存(在本例中为
value

但是您指定了
allow\u nil:false
,这意味着该选项无论如何都不适用

总之,您第一次使用
allow_value
失败,因为
nil
不是
key
的有效值(包含验证失败)。但是,第二种用法通过了,因为
nil
的有效值(前提是没有
nil
的现有记录)

我想,我的观点是,如果你真的想测试你的验证,你应该使用与这些验证直接对应的匹配器:

it do
  should validate_inclusion_of(:key).
    in_array(["TITLE", "DEPARTMENT", "LOCATION"]).
    allow_nil
end

it do
  should validate_uniqueness_of(:value).
    scoped_to(:key).
    case_insensitive
end

为什么不直接使用状态验证器呢?我认为这是因为范围条款的缘故。也只是性能方面的问题,但您可能希望冻结keys enum的每个字符串和数组,否则它们是使用每个模型实例创建的。这很有意义,谢谢!我猜
allow_nil
的目的不是描述字段的值,而是标记验证本身是否应该为
nil
值运行。正如你提到的,这似乎有点误导,但谢谢你澄清
it do
  should validate_inclusion_of(:key).
    in_array(["TITLE", "DEPARTMENT", "LOCATION"]).
    allow_nil
end

it do
  should validate_uniqueness_of(:value).
    scoped_to(:key).
    case_insensitive
end