Create single form, user and client registries?

Hi,
how can I make a single form, fill in several other tables?

For example.
I have a registration form with the following columns (user, email, password) of the user table.

I have another registration form with the following columns (city, state, zip …) of the clients table

I need to create a single form that I can insert in the table “user, clients”

Note:
In the user form, I registered city, state, zip code.
But when I’m going to save the user, it’s just insert the user, email, password.

Below is my user controller.

  def new(conn, _params, user) do
    changeset = Registro.change_user(%User{})
    render(conn, "new.html", changeset: changeset, user: user)
  end

  def create(conn, %{"user" => user_params}, user) do
    case Registro.create_user(user_params) do
      {:ok, user} ->
        conn
        |> put_flash(:info, "Usuário #{user.username} criado com sucesso.")
        |> redirect(to: user_path(conn, :show, user))
      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "new.html", changeset: changeset, user: user)
    end
  end

I would use Ecto.Multi and Repo.Transaction in your context function to insert the params in multiple tables. I’m on mobile so hard to paste examples in here but you can refer to the excellent documentation… it’s pretty straightforward.

1 Like

Maybe this Ecto.Multi example can help:

Best regards.

As an alternative to the other suggestions here, you could also use nested inputs and cast_assoc/3. This would only make sense if the nested inputs were properties on an association of the main form item.

1 Like

I thought I’d better use Ecto.Multi.
But I’m having difficulty adding it to my controller?
could you help me with an example?

If user is associated with client, I would use cast_assoc/3

I think your controller looks good as it is… basically it’s calling your context function Registro.create_user(user_params) then dealing with the success case and the error case after that. It’s in the context that the real logic should go which creates the Multi and runs the atomic database transaction.

I don’t have generic code handy for the pattern but this post, the comment by Michał, and the linked discussion with José shows the way: https://medium.com/@abitdodgy/building-many-to-many-associations-with-embedded-schemas-in-ecto-and-phoenix-e420abc4c6ea

Unlike that example which was probably based on Phx 1.2, I would do all of the Repo.Transaction stuff in the context function Registro.create_user instead of the controller but the pattern is the same. Hope this helps!