Ash FrameworkAF
Ash Framework7mo ago
6 replies
Joan Gavelán

Help with multi-step resource creation in Ash (Phoenix + React)

I’m building a multi‑tenant app with this structure:
user → organization → establishment → establishment_user

In my flow, a user creates both an organization and an establishment, and the system automatically creates the establishment_user behind the scenes.

What I have:

# organization.ex
create :create_organization do
  argument :establishment, :map
  change relate_actor(:owner)

  change after_action(fn changeset, org, context ->
    # I’m doing this to return establishment validation errors back to the frontend.
    # However, I had to change the attribute names (e.g., "name" → "organization_name"/"establishment_name")
    # in both Organization and Establishment resources to differentiate them in my Inertia form—otherwise
    # it couldn't map the error to the right field.
    # Is this the best approach?
    case Lamashka.Establishments.create_establishment(
           changeset.arguments.establishment,
           actor: context.actor,
           tenant: org
         ) do
      {:ok, _establishment} -> {:ok, org}
      {:error, error} -> {:error, error}
    end
  end)
end

# establishment.ex
create :create_establishment do
  change after_action(fn _changeset, est, context ->
    Lamashka.Establishments.add_establishment_user!(
      %{user_id: context.actor.id, role: :admin},
      tenant: est
    )

    {:ok, est}
  end)
end

# establishment_user.ex
create :add_establishment_user do
  accept [:user_id, :role]
end


My questions:

- Could I have used manage_relationship/4 for this, or is after_action/3 my only option due to setting different tenants?

- Do all three actions run in a single transaction?

- How can I implement policies correctly in this setup? With manage_relationship, I could use accessing_from/2 in my policies, but that doesn’t seem to work when using after_action, so I’m bypassing policies entirely for now

This setup is working btw (aside from policies), just making sure it’s the right way to do it.
Solution
1. after_action was the right choice, you can't set a different tenant with manage_relationship AFAIK
2. all run in the same transaction, the first action call opens the transaction and all the after action starts the next action in the same transaction
3 . all accessing_from is checking is a certain value in the context, so you could just manually set the context when calling the other actions inside after_action
Was this page helpful?