AF
Ash Framework•4mo ago
Steve

AshPhoenix.Form.submit is triggering change function to run twice

Say I have a custom change module, like so:
defmodule MyApp.Accounts.Changes.MyCoolChange do
use Ash.Resource.Change

@impl true
def init(opts) do
{:ok, opts}
end

@impl true
def change(changeset, _opts, _context) do
dbg("my cool change")
changeset
end
end
defmodule MyApp.Accounts.Changes.MyCoolChange do
use Ash.Resource.Change

@impl true
def init(opts) do
{:ok, opts}
end

@impl true
def change(changeset, _opts, _context) do
dbg("my cool change")
changeset
end
end
When I run this in the iex terminal, the dbg statement only gets output once. That's what I would expect. Now, when I use it in form using AshPhoenix.Form, I get the dbg statement two times when doing Form.submit. I even took out all other code so this was the only thing running. The mount would look like this:
def mount(socket)
socket =
socket
|> assign(form: to_form(MyApp.Domain.to_form_my_action())

{:noreply, socket}
def mount(socket)
socket =
socket
|> assign(form: to_form(MyApp.Domain.to_form_my_action())

{:noreply, socket}
Inside the my_action action, it would look like this:
actions do
create :my_action do
argument :my_arg, :string, allow_nil?: false
change MyCoolChange
end
end
actions do
create :my_action do
argument :my_arg, :string, allow_nil?: false
change MyCoolChange
end
end
Then the event handler looks like this:
def handle_event("submit", %{"form" => form_data}, socket) do
case Form.submit(socket.assigns.form, params: form_data}) do
{:ok, result} ->
# ...

{:error, form} ->
# ...
end
end
def handle_event("submit", %{"form" => form_data}, socket) do
case Form.submit(socket.assigns.form, params: form_data}) do
{:ok, result} ->
# ...

{:error, form} ->
# ...
end
end
With all this in place, the dbg message at the start ("my cool change") ends up being called two times. I can put a dbg in the handle_event and it's only called once. I've checked everywhere along the path and it's during the Form.submit call that it happens two times. Is that expected behavior or a bug? If I debug inside something like a before_action that is defined in that same change module, the before_action debug only gets called once, same with action_action. But any code inside that change function at the root gets run two times.
7 Replies
ZachDaniel
ZachDaniel•4mo ago
This is by design 😄 the body of changes are meant to be for cheap setup that can run validations on keypress and hooks are designed to schedule logic for when the action is actually run
Steve
SteveOP•4mo ago
Ah, so anything else should be done in those hooks like before_action and after_action then?
ZachDaniel
ZachDaniel•4mo ago
Yep! Any side effects, or especially slow work etc.
Steve
SteveOP•4mo ago
I was going crazy trying to figure out what was going on. It took a while to track it down hahah. I assume even though that change function is run twice, it doesn't seem to queue the hooks more than once, right?
Elixord
Elixord•4mo ago
Hexdocs Search Results
Searched ash-3.5.21 for multi-step
ZachDaniel
ZachDaniel•4mo ago
Correct The form discards and rebuilds the underlying changeset each time So its a fresh changeset w/ no hooks each time, and so hooks don't get doubled up etc. That guide I linked has some useful info on hooks, how they work and why etc.
Steve
SteveOP•4mo ago
All right, I feel much better now knowing this. Thanks very much!

Did you find this page helpful?