mirror of
https://github.com/thoughtbot/shoulda-matchers.git
synced 2022-11-09 12:01:38 -05:00
afa6a7b666
Instead of using describe Foo do # ... end use RSpec.describe Foo, type: :model do # ... end instead. This is not exactly official, as the former style still works, but the latter style is highly suggested in RSpec documentation and the like, so this is what people are used to. [ci skip]
111 lines
4 KiB
Markdown
111 lines
4 KiB
Markdown
# @title NonCaseSwappableValueError
|
|
|
|
# NonCaseSwappableValueError
|
|
|
|
This error is raised when using `validate_uniqueness_of`. This matcher, of
|
|
course, tests that an attribute disallows a non-unique value -- and what
|
|
constitutes as "unique" depends on whether the case-sensitivity of that value
|
|
matters. If it does matter -- meaning that the uniqueness validation in your
|
|
model isn't using `case_sensitive: false` and you haven't qualified the matcher
|
|
with `case_insensitive` -- then the matcher will run the following test:
|
|
|
|
> Creating first a record with a value of "A":
|
|
>
|
|
> * A new record with a value of "A" should not be valid (failing the uniqueness
|
|
> validation)
|
|
> * A new record with a value of "a" should be valid
|
|
|
|
The test value we're using is in this case "A", and this is what the matcher
|
|
will use if an existing record is not already present in the database. But if
|
|
a record already exists, then the matcher will use it as comparison -- it will
|
|
read the attribute under test off of the record and use its value. So a better
|
|
example might be:
|
|
|
|
> Given an existing record with a value:
|
|
>
|
|
> * A new record with the same value should not be valid (failing the uniqueness
|
|
> validation)
|
|
> * A new record with the same value, but where the case is swapped (using
|
|
> String#swapcase), should be valid
|
|
|
|
Now, what happens if an existing record is there, but the value being used is
|
|
not one whose case can be swapped, such as `"123"` or `"{-#%}"`? Then the second
|
|
assertion cannot be made effectively.
|
|
|
|
So this is why you're getting this exception. What can you do about it? As the
|
|
error message explains, you have two options:
|
|
|
|
1. If you want the uniqueness validation in the model to operate
|
|
case-sensitively and you didn't mean to use a non-case-swappable value,
|
|
then you need to provide an existing record with a different value, one that
|
|
contains alpha characters. Here's an example:
|
|
|
|
# Model
|
|
class User < ActiveRecord::Base
|
|
validates_uniqueness_of :username
|
|
end
|
|
|
|
# RSpec
|
|
RSpec.describe User, type: :model do
|
|
context "validations" do
|
|
subject do
|
|
# Note that "123" == "123".swapcase. This is a problem!
|
|
User.new(username: "123")
|
|
end
|
|
|
|
it do
|
|
# So you can either override it like this, or just fix the subject.
|
|
user = User.create!(username: "john123")
|
|
expect(user).to validate_uniqueness_of(:username)
|
|
end
|
|
end
|
|
end
|
|
|
|
# Minitest (Shoulda)
|
|
class UserTest < ActiveSupport::TestCase
|
|
context "validations" do
|
|
subject do
|
|
# Note that "123" == "123".swapcase. This is a problem!
|
|
User.new(username: "123")
|
|
end
|
|
|
|
should "validate uniqueness of :username" do
|
|
# So you can either override it like this, or just fix the subject.
|
|
user = User.create!(username: "john123")
|
|
assert_accepts validate_uniqueness_of(:username), record
|
|
end
|
|
end
|
|
end
|
|
|
|
2. If you don't want the uniqueness validation to operate case-sensitively,
|
|
then you need to add `case_sensitive: false` to the validation and add
|
|
`case_insensitive` to the matcher:
|
|
|
|
# Model
|
|
class User < ActiveRecord::Base
|
|
validates_uniqueness_of :username, case_sensitive: false
|
|
end
|
|
|
|
# RSpec
|
|
RSpec.describe User, type: :model do
|
|
context "validations" do
|
|
subject do
|
|
# Note that "123" == "123".swapcase, but it's okay
|
|
User.new(username: "123")
|
|
end
|
|
|
|
it { should validate_uniqueness_of(:username).case_insensitive }
|
|
end
|
|
end
|
|
|
|
# Minitest (Shoulda)
|
|
class UserTest < ActiveSupport::TestCase
|
|
context "validations" do
|
|
subject do
|
|
# Note that "123" == "123".swapcase, but it's okay
|
|
User.new(username: "123")
|
|
end
|
|
|
|
should validate_uniqueness_of(:username).case_insensitive
|
|
end
|
|
end
|