How do I do this SQL UPDATE-query in Ash?

I want to update a row in a database table if it exists, and otherwise return an error. In SQL I would do something like this:
UPDATE hats SET activation_token = null, activated = NOW() WHERE activation_token = ...
UPDATE hats SET activation_token = null, activated = NOW() WHERE activation_token = ...
I tried with an update-action in Ash, because that seemed like the natural first thing to try, but then I have to give it a record as a first argument and I don't have a record, that's what I want to lookup with the activation_token, and now every other solution doesn't really fit into my idea of how this should be solved. How should I go about solving this? What's the cleanest or maybe most idiomatic way to write this kind of functionality?
Solution:
```elixir require Ash.Query # needed for filter bulk_result = Hats...
Jump to solution
7 Replies
sevenseacat
sevenseacat•2mo ago
I feel like you would want to look up the record by activation token first, and then update it to say that it's been used. eg. if you had an identity on the activation_token field to ensure it's unique, you could do something like Ash.get(YourResource, activation_token: the_token) and then call another action to activate it
Andreas Ekeroot @ work
Andreas Ekeroot @ workOP•2mo ago
Got it, then I'll do that. I have a tendency to be enamoured by SQL and try to use that kind of thinking everywhere, even when it's not appropriate.
barnabasj
barnabasj•2mo ago
Also, with bulk_updates, you can pass a filter instead of a resource
sevenseacat
sevenseacat•2mo ago
SQL is cool and all, but doing it like that in SQL couldn't raise/return an error if no rows matched
Andreas Ekeroot @ work
Andreas Ekeroot @ workOP•2mo ago
It could raise an error, but it's a bit roundabout, I would have to look for how many rows were updated and if that is 0, then raise error. 🙂 I have no idea how to do this in Ash.
Solution
barnabasj
barnabasj•2mo ago
require Ash.Query # needed for filter

bulk_result =
Hats
|> Ash.Query.for_read(:read_action_name, %{}, scope: your_scope)
|> Ash.Query.filter(activation_token == ^activation_token)
|> Ash.bulk_update(:update_action_name, %{your: changes}, scope: your_scope, return_records?: true)

if bulk_result.satus != :success || length(bulk_result.records) == 0 do
raise "some kind of error"
end
require Ash.Query # needed for filter

bulk_result =
Hats
|> Ash.Query.for_read(:read_action_name, %{}, scope: your_scope)
|> Ash.Query.filter(activation_token == ^activation_token)
|> Ash.bulk_update(:update_action_name, %{your: changes}, scope: your_scope, return_records?: true)

if bulk_result.satus != :success || length(bulk_result.records) == 0 do
raise "some kind of error"
end
Andreas Ekeroot @ work
Andreas Ekeroot @ workOP•2mo ago
Sweet! Now I have somewhere to start! Thank you!

Did you find this page helpful?