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
Make enums validatable without raising error #49100
Make enums validatable without raising error #49100
Conversation
@@ -209,7 +256,7 @@ def _enum(name, values, prefix: nil, suffix: nil, scopes: true, instance_methods | |||
|
|||
attribute(name, **options) do |subtype| | |||
subtype = subtype.subtype if EnumType === subtype | |||
EnumType.new(name, enum_values, subtype) | |||
EnumType.new(name, enum_values, subtype, raise_on_invalid_values: !validate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it expected for an ArgumentError
to be raised when we explicitly include validate: false
in the enum
definition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that is the case, why do we need the validate
option, since we are raising the error for both cases? I mean for 'true' and 'false' cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you don't need pass validate: false
. Like in belongs_to
you don't need to pass optional: false
explicitly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TLDR:
- when
:validate
is falsey (by default) — standard "old" behaviour with raising error - when
:validate
is truthy (need explicit specify) — soft adding of validation message
Detailed:
ArgumentError
raises only if the validate
argument is falsy (validate: nil
or validate: false
) and only if you try to assign invalid value. It is current behaviour of enum
before this PR. And PR suggests keep this behaviour as is. That's why these change don't break legacy code. And you don't need pass validate: false
explicitly. It is redundant like with above example (belongs_to :user, optional: false
— it is unlikely somebody write)
If pass truthy validate
argument, enum is validated with rails inclusion validation. If you try to assign invalid value, a validation error is added to the model instance (ArgumentError
doesn't raise). But ActiveRecord::RecordInvalid
can raise if use bang methods save!
, create!
etc.)
Please see examples in the PR description and tests. I think it will be more understandable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense @mechnicov. Thanks :)
|
Or invert the meaning
|
@rafaelfranca yes, probably there is some ambiguity when we talk about validation in this particular case
I was also thinking about |
hmm. Good point. I think |
d8b419b
to
6ee0d5e
Compare
Since #41730 is the original work for the enum attribute validation.
Motivation / Background
There is a pretty old issue #13971
@dhh offered to make such contributions in 2017
But opened MR #41730 was not maintained since 2021
I tried to take into account the comments in that code review
Detail
This Pull Request adds
:validate
option for enumsIf you want the enum value to be validated before saving, use the option
:validate
:It is also possible to pass additional validation options:
Otherwise
ArgumentError
will raise (standard current behavior):Additional information
This was intended as non-breaking change
Checklist
[Fix #issue-number]