rails: ActiveRecord enum: use validation if exists instead of raising ArgumentError
Regarding ActiveRecord::Enum, assume you had something like
class Project < ActiveRecord::Base
enum color: [:blue, :green, :red]
validates :color, inclusion: { in: [:blue, :green, :red] }
end
Currently, if a “bad” value (say, “orange”) is passed in, an ArgumentError
is raised.
It would be nice if the validation was preferred (with the ArgumentError
as a fallback if there was no validation on that attribute) so that you’d be able to return a nicer error on the object later via the standard means:
object.errors.messages
# => {:color=>["is not included in the list"]} kind of thing
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Reactions: 92
- Comments: 31 (10 by maintainers)
Links to this issue
- validation - How do i specify and validate an enum in rails? - Stack Overflow
- Rails validating enums - Stack Overflow
- ruby on rails - How to test enum validation? - Stack Overflow
- Rails enum validation not working but raise ArgumentError - Stack Overflow
- Enum validation in Rails 4.2 doesn't work - Stack Overflow
- ruby - How to write validation for enum in rails - Stack Overflow
- Rails 4 enum validation - Stack Overflow
Commits related to this issue
- Mainly green specs for players controller 4 yellows due to rails bug https://github.com/rails/rails/issues/13971, skip tag in code. — committed to hughdavenport/powershop_devtrain_monopoly by deleted user 8 years ago
- skip testing invalid pieces. due to https://github.com/rails/rails/issues/13971 — committed to hughdavenport/powershop_devtrain_monopoly by deleted user 8 years ago
- Endpoint to persist the dismissal of a user's health care notification status (#3000) * Endpoint to create a new dismissed status notification * Enforces that a user cannot have a duplicate notifi... — committed to department-of-veterans-affairs/vets-api by hpjaj 5 years ago
- Propose a way to add validation on the enum attribute Last year, I heard about the inconveniences of ActiveRecord Enum and got some feedback (one of those is #40456). Some people have reported that ... — committed to kamipo/rails by kamipo 3 years ago
In Rails 5.2, you can override
assert_valid_value
ininitializers/active_record_enum.rb
as follow:Instead raise ArgumentError. You will set
nil
to a invalid value.So, you can validate the enum as follow:
Or if you want to use the value before casting you can use the attribute
self.gender_before_type_cast
to validate raw input.You can put a happy face on the situation by volunteering to work on it 😄. Rails is always open to new contributors!
Hi, we do implement a REST API and have something like this in our controller:
Our model has an enum attribute called
kind
, and if we receive an invalid value theArgumentError
being raised, the user receives 500 error code. And I don’t see a good way to handle this at our end. We have to manually validate submitted values in controller, create additional services for that, etc. Doesn’t seem right to me.It would be helpful if it at least raise a more specific error, like ActiveRecord::EnumValueError or something like that.
Just run into this issue. To me, the behavior of AR enum is surprising. I would not expect this code to raise an ArgumentError
In my experience, AR enums are used as user-facing attributes A LOT. Community have several gems that addresses enum issues (e.g. enumerize gem or the enum_attributes_validation mentioned above). But I think rails should address these issues and provide better experience with enums out of the box. Would be glad to help with that issue.
Hi there! I’d like to challenge the reason this issue got closed. I believe the fact that we have 240+ (🙀) gems for the
enum
keyword is one of the effects of closing this conversation.Would you be so kind re-opening this issue pretty please? 🙏 At least it will suggest we’re open for contributions (and it seems like we are):
Agree with @chancancode. The current focus of AR enums is to map a set of states (labels) to an integer for performance reasons. Currently assigning a wrong state is considered an application level error and not a user input error. That’s why you get an
ArgumentError
.I’m closing this for now but please do as @chancancode proposed and start a discussion on the mailing list.
@tjschuck thank you for using the beta 💛 !
If you are looking for a quick fix you can add this to your
application_record.rb
. It will suppress the exception when you have a validation for the enum defined.i have made a gem for validating enums inclusion https://github.com/CristiRazvi/enum_attributes_validation
Ugg… just ran into this. Sad to see that two years later there’s still no built in validation for enums.
Folks, please weight on #41730 to get it merged and get this issue closed 🙏 🙌 !!!
I’ve found a solution. Tested by myself in Rails 6.
Usage:
@heaven:
You should absolutely do that 👍
Also we don’t take feature requests on here, try the Rails Core mailing list to see if you can garner support on your proposal. Thanks ❤️
Here’s a variation on @stas’s solution that appears to work in 6.0.3.4:
After I wrote all that stuff in the previous comment, I discovered https://github.com/makandra/assignable_values, which I think is actually a waaaay better solution!
This has been implemented: https://github.com/rails/rails/pull/49100
@chancancode Do you think this is still a non issue? Or can I work on providing support for enums through out the entire process? I can work on form builders, scaffolding and validation. Please let me know your thoughts.