-
-
Notifications
You must be signed in to change notification settings - Fork 910
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
validate_uniqueness_of does not account for reliance on other records in other validations #1435
Comments
Hi @brett-puddick, In general shoulda-matchers does not do anything to fill in attributes on records, so whenever working with validation matchers it works a lot better if you always use a record that satisfies all of the validations. That said, the uniqueness matcher is a weird case, and I agree that it would make more sense to prefer making use of the given record rather than always relying on other data outside of it. I think that particular behavior is a vestige from a long time ago. In fact I remember that someone else raised this issue a while back and I gave some thoughts on it then: #1067. Even though the matcher works in a weird way, I am now not sure whether it now be a good idea to change it fundamentally, as it would technically be a breaking change, and we're more or less feature frozen on the next release. That said, one idea I just thought of would be to change the behavior, but then make it opt-in. That is, add a new configuration option to |
The workaround fails if your scope includes the model. For example this fails for me: model Account
belongs_to :organization
validates :email uniqueness: { case_sensitive: false, scope: :organization_id }
validates :payment_account, presence: true, on: :create, if: -> { organization.requires_payment? }
end RSpec.describe Account, type: :model do
subject(:account) { build(:account) }
describe 'validations' do
it do
account.organization = create(:organization)
is_expected.to validate_uniqueness_of(:email).case_insensitive.scoped_to(:organization_id)
end
end
end as the matcher is setting (on one of the runs) an invalid Debugging what the matcher was doing - it run perform_validation 5 times - the last time the For now I'm just removing the validation / spec alltogether as I couldn't find a useful workaround using shoulda-matchers |
- Add migration to fix the unique index - Add scope to the uniqueness validation - Add user factory - Add user association to lesson factory - Lesson factory corrections - Add section factory - Add section model spec NOTE: We modify the start_time and end_time validations to provide a default value for lesson.duration_in_seconds because there's an issue with shoulda matchers and validations that refer to associated models according to this issue thoughtbot/shoulda-matchers#1435
- Add migration to fix the unique index - Add scope to the uniqueness validation - Add user factory - Add user association to lesson factory - Lesson factory corrections - Add section factory - Add section model spec NOTE: We modify the start_time and end_time validations to provide a default value for lesson.duration_in_seconds because there's an issue with shoulda matchers and validations that refer to associated models according to this issue thoughtbot/shoulda-matchers#1435
So, let's say we have:
and then we want to test the uniqueness validation:
The observed behaviour of what happens in this test is that the matcher takes the first record in the DB (not necessarily the one you provided), builds a new instance of it (without saving) and then goes about its checks manipulating attribute values and asserting if it's valid.
This approach does not take into concern that other validations may fail, and hence the test, as the model has reliances on other data outside of this record. The matcher should either use the record provided (with an expectation that it passes all other required validations) or also build new instances of any associations when grabbing the first record from the DB.
The text was updated successfully, but these errors were encountered: