Setting attributes after getting data in before_transaction - calling validation in change_attribute
I have a
User
resource which requires email and a name. I want to expose a create type action on this resource, but all I have available when calling the action is a token. That token is in a 3rd party system, which returns the name and email. This resource has global validation on name and email, which I'd rather not change (or mark as before_action?: true
) since I do want them to be run up front for other actions.
What I was hoping to do is in a before_transaction
block, make the API call to get the data and set the attributes with change_attribute
, or put them in a context and call set_attribute
in a change block. However, when I do this, since the initial changeset doesn't have an email, it fails validation and the before_transaction never runs. If I pass in a placeholder email, I can get the before_transaction
to run, but then I get warnings when calling change_attribute
because the changeset has already been validated, and it's actually possible to pass in a bad email here and it'll get written to the database.
Another idea I had was to try and do this as a generic action, and then in the run block I would make the API call, get the user data, and then manually call the existing :create
. However, I need to return metadata (access tokens) for the user, but it seems like generic actions don't allow for metadata blocks, and since this action will be exposed via GraphQL, I'd want that typing of the metadata attributes on the query/mutation.
Basically, I want to expose an action on a user resource that accepts a token as an argument, turns that into user_info
and oauth_tokens
and then can do the equivalent of the :register_with_google
action in the Ash Authentication docs, returning the access token for the user as a metadata field.
Note, I'll never really call this in a form, so I'm ok if the fields don't get validated until writing to the persistence layer (postgres in my case), but I do want them to be validated at some point.Solution:Jump to solution
I think this is what you want https://hexdocs.pm/ash/dsl-ash-resource.html#actions-create-delay_global_validations? ?
5 Replies
Solution
I think this is what you want https://hexdocs.pm/ash/dsl-ash-resource.html#actions-create-delay_global_validations? ?
I think you still need to use force_change_attribute in before_transaction but as the validation now runs after in before_action it should still validate those attributes
That works great if you have it set to allow_nil? false
Oh nice, I didn't see those. It looks like both
delay_global_validations
and allow_nil_input
would serve my needs.
Though it seems like since i'm not accepting email
or name
as an argument then allow_nil_input
wouldn't really apply in my case.
I think delay_global_validations
plus using force_change_attribute
to remove the warning is enough to unblock me. Thanks!