我有一个User具有items. 该:name项目的应该是用户唯一的,但它应该允许不同的用户拥有的项目具有相同名称。
Item 模型当前设置为:
class Item < ApplicationRecord
belongs_to :user
validates :name, case_sensitive: false, uniqueness: { scope: :user }
end
Run Code Online (Sandbox Code Playgroud)
这适用于验证内部用户,但仍允许其他用户使用相同的名称保存项目。
我如何使用 RSpec/Shoulda 进行测试?
我目前的测试是这样写的:
describe 'validations' do
it { should validate_uniqueness_of(:name).case_insensitive.scoped_to(:user) }
end
Run Code Online (Sandbox Code Playgroud)
但是这个测试失败了,因为:
Failure/Error: it { should validate_uniqueness_of(:name).scoped_to(:user).case_insensitive }
Item did not properly validate that :name is case-insensitively
unique within the scope of :user.
After taking the given Item, setting its :name to ‹"an
arbitrary value"›, and saving it as the existing record, then making a
new Item and setting its :name to a different value, ‹"AN
ARBITRARY VALUE"› and its :user to a different value, ‹nil›, the
matcher expected the new Item to be invalid, but it was valid
instead.
Run Code Online (Sandbox Code Playgroud)
然而,这是我想要的行为(除了应该nil为用户选择的奇怪部分)。当用户不同时,相同的名称应该是有效的。
可能是我没有正确使用范围测试,或者这对应该是不可能的,这里是范围测试的描述。在这种情况下,您将如何编写模型测试来测试这种行为?
解决这个问题的方法有三:
范围到:user_id而不是:user在模型中
重新编写模型的验证以包含所有唯一性要求作为散列的一部分
:user_id问题中的代码将起作用,因为它不区分大小写地正确检查唯一性,但最好将所有唯一性要求包括为散列,因为文档中的示例即使对于单个声明也采用这种形式(而且,它是唯一的我可以找到使应该以正确的行为通过测试的方式)。
这是工作代码的样子:
模型
class Item < ApplicationRecord
belongs_to :user
validates :name, uniqueness: { scope: :user_id, case_sensitive: false }
end
Run Code Online (Sandbox Code Playgroud)
测试
RSpec.describe Item, type: :model do
describe 'validations' do
it { should validate_uniqueness_of(:name).scoped_to(:user_id).case_insensitive }
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2333 次 |
| 最近记录: |