I have a set of custom validations and changes that are tightly coupled together.
Imagine a create
action:
...
validate check_something_about(:forms, extra_param)
change do_something_to(:forms, extra_param)
...
What is the “Ash” way of approaching this?
Should the validations and the changes be separated out (as in the example above) or should it all happen in the change, leveraging Ash.Changeset.add_error/3
to report errors?
Thanks.
Its an interesting question. What exactly makes them coupled? Are you expecting to reuse this combination in the future? There are a few ways to do it:
Call validations from the change
You could combine it by calling the validations in the change. If you have a reusable validation that you want wrapped into a bigger change.
with :ok <- Validation.validate(changeset, ...),
:ok <- OtherValidation.validate(changeset, ...) do
end
Macro it
You could define a macro that includes both:
defmacro check_and_validate(key, param) do
quote do
check_something_aboute(:forms, extra_param)
do_something_to(:forms, extra_param)
end
end
And then in the action
create :create do
change_and_validate(:forms, extra_param)
end
Share functionality with functions
If they are coupled in terms of functionality, then you could define a module with functions in it that allow them to share this functionality.
def change(changeset, _, _) do
SharedBehavior.foo(changeset)
end
def validate(changeset, _) do
SharedBehavior.foo(changeset)
end
Put it all in the change
At the end of the day, its perfectly acceptable to do a “validation” inside of a change, returning an error as you mentioned. Change modules are meant to be that outlet when their simpler counterpart, validations, don’t suffice.
2 Likes