:one_of constraint for type string
gvanders:
There exists :one_of constraint for type :atoms on the resources, but this does not exist for type :string. Is there another way to restrict values to one of a list of strings?
ZachDaniel:
There are a few other ways, yes 🙂
ZachDaniel:
You can add a validation like so:
validations do
validate one_of(:attribute, [“foo”, “bar”])
end
gvanders:
Thanks! With constraints I’m able to access the list (say for Option generation for select component) with
Ash.Resource.Info.attribute(resource, :options).constraints[:one_of]
To do the same thing I guess I need to write a function which pulls it from
Ash.Resource.Info.validations ?
ZachDaniel:
hmm…yeah that’s probably the only way at the moment
ZachDaniel:
what do you use that info for, out of curiosity?
ZachDaniel:
We could potentially add support for
one_of on all types
gvanders:
Mainly for forms and building values of selects. For the form on the UI I can grab the list to generate the options and keep those two in sync
gvanders:
That would be great! Because from my understanding doing operations with changesets (Changeset.change_attributes), the constraints correctly limit it, but with validations it only kicks in once acted upon?
ZachDaniel:
You’ll get errors for all of them on validation
ZachDaniel:
I’ll have to think about it because there are some implementation considerations.
gvanders:
gvanders:
Errors with constraints:
gvanders:
Valid with validations
ZachDaniel:
yeah, but when you run the changeset action it will give you the errors, which is what happens on
AshPhoenix.Form.validate/2 for example
ZachDaniel:
what I would suggest: write a custom type called
YourApp.StringEnum that has a
one_of constraint 😄
gvanders:
I’m gonna have a lot of them 😅 . As far as implementation, I just copied atom implementation over which works. If there are larger architecture decisions that I’d understand I’d be happy to make a PR with those too
ZachDaniel:
That looks right to me 🙂 I’m not convinced that we necessarily want to add the constraint to all types yet, so for now I think the custom type is the right answer. I’ll let the idea percolate though