Skip to content

Add ComparisonValidator to validate comparison of any objects#40095

Merged
matthewd merged 2 commits intorails:mainfrom
ChaelCodes:cc-comparablity-validator
Apr 24, 2021
Merged

Add ComparisonValidator to validate comparison of any objects#40095
matthewd merged 2 commits intorails:mainfrom
ChaelCodes:cc-comparablity-validator

Conversation

@ChaelCodes
Copy link
Copy Markdown
Contributor

Summary

We allow for compare validations in NumericalityValidator, but these
only work on numbers. There are various comparisons people may want
to validate, from dates to strings, to custom comparisons.

validates_comparison_of :end_date, greater_than: :start_date

Other Information

My main reason for creating this validator is the number of workarounds for validating that a start_date begins before an end_date.

Instead of making something specific like a date validator, I thought it would be helpful to create a generic comparison validator, to support a variety of circumstances, including custom comparables.

Comment thread guides/source/active_record_validations.md Outdated
Comment thread activemodel/lib/active_model/validations/comparison.rb Outdated
Comment thread activemodel/lib/active_model/validations/comparison.rb Outdated
Comment thread activemodel/test/cases/validations/comparison_validation_test.rb Outdated
Comment thread activemodel/test/cases/validations/comparison_validation_test.rb Outdated
Comment thread guides/source/active_record_validations.md Outdated
Comment thread guides/source/active_record_validations.md Outdated
Comment thread guides/source/active_record_validations.md Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to suggest "supplied" to avoid passed/pass... but maybe it should just be an immediate error to define a comparison validation without any constraints?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any existing patterns for this? I think this is the first validator that needs checks to validate anything.

I leaned towards no error in case someone dynamically supplied options, and they were missing. I also thought if there were no constraints, then there should be no errors. I can also see the argument that an error could help nudge people who've misconfigured the comparison validator.

The way I see it, we have 3 options:
👀 Error if no options supplied
🚀 Pass if no options supplied
🎉 Validate if the attribute is comparable if no options supplied, making the checks optional

I don't have a strong preference, and they're all pretty easy to implement.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it's taken me a silly amount of time to come back to this...

I believe this is what check_validity! is for. Numericality only does a typecheck [because it always implies the must-be-a-number constraint, even without any further options], but Length and Format have precedent for "you can supply any of these options, but must supply at least one (or for Format, exactly one).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I'll update the tests, code, and guide.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made the requested changes!

@matthewd
Copy link
Copy Markdown
Member

👋🏻!

What do you think about having NumericalityValidator inherit from this, such that it ends up being "make_sure_its_a_number && super"?

Worth considering as a future change, or probably not worth it?

@ChaelCodes
Copy link
Copy Markdown
Contributor Author

@matthewd
👋!

I tried out the inheritance and it ended up being more trouble than expected. With a decent refactor to NumericalityValidator though, I can add a Comparability module similar to Clusivity.
I'm working on that and will update soon!

@ChaelCodes ChaelCodes force-pushed the cc-comparablity-validator branch from c342309 to 9bf9685 Compare August 29, 2020 23:48
@ChaelCodes ChaelCodes requested a review from matthewd September 7, 2020 20:23
@ChaelCodes
Copy link
Copy Markdown
Contributor Author

This PR is ready to review. Let me know if there are any other requested changes. I'd be happy to implement them.

Base automatically changed from master to main January 14, 2021 17:01
…omparable values.

We allow for compare validations in NumericalityValidator, but these
only work on numbers. There are various comparisons people may want
to validate, from dates to strings, to custom comparisons.

```
validates_comparison_of :end_date, greater_than: :start_date
```

Refactor NumericalityValidator to share module Comparison with ComparabilityValidator
* Move creating the option_value into a reusable module
* Separate COMPARE_CHECKS which support compare functions and accept values
* Move odd/even checks to NUMBER_CHECKS as they can only be run on numbers
@ChaelCodes ChaelCodes force-pushed the cc-comparablity-validator branch from b9c1557 to 9a08a2f Compare January 24, 2021 02:25
@ChaelCodes
Copy link
Copy Markdown
Contributor Author

@rafaelfranca @matthewd I've just rebased to incorporate the new changes to NumericalityValidator, and renamed valid!, and invalid!. Please let me know if there's anything else I can do for this PR.

@rails-bot
Copy link
Copy Markdown

rails-bot bot commented Apr 24, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.

@rails-bot rails-bot bot added the stale label Apr 24, 2021
@rails-bot rails-bot bot removed the stale label Apr 24, 2021
@matthewd matthewd merged commit 536a2c0 into rails:main Apr 24, 2021
@ChaelCodes ChaelCodes deleted the cc-comparablity-validator branch April 24, 2021 11:37
def check_validity!
unless (options.keys & COMPARE_CHECKS.keys).any?
raise ArgumentError, "Expected one of :greater_than, :greater_than_or_equal_to, "\
":equal_to, :less_than, :less_than_or_equal_to, nor :other_than supplied."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ChaelCodes Typo: nor -> or

I would also add option in the exception message like: ... or :other_than option supplied.

kamipo added a commit that referenced this pull request Apr 25, 2021
It was accidentally changed in #40095.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants