Hello there, I looked up a topic with a similar error and they recommended to write “rm -rf _build” and recompile, but this did not help me, so I am creating a new topic.
I have two schemas: “users” and “users_details”, which have 1:1 relations.
And my LiveView template is:
<%= form_for @user_changeset, "#",
[phx_change: :validate, phx_submit: :save, phx_hook: "SavedForm"], fn f-> %>
<%= label f, :email %>
<%= text_input f, :email, phx_debounce: "blur" %>
<%= error_tag f, :email %>
<%= inputs_for f, :users_details, fn f2 -> %>
<%= label f2, :first_name %>
<%= text_input f2, :first_name, phx_debounce: "blur" %>
<%= error_tag f2, :first_name %>
<% end %>
<div>
<%= submit "Save", phx_disable_with: "Saving..." %>
</div>
<% end %>
In my mount function i get user by session token and pass into socket user_changeset (with preloaded users_details) and user struct
def mount(_params, %{"user_token" => user_token}, socket) do
user =
Accounts.get_user_by_session_token(user_token)
|> Repo.preload(:users_details)
user_changeset =
user
|> User.changeset(_params)
{:ok,
assign(socket, %{
user_changeset: user_changeset,
user: user,
})}
end
Here’s my handle_event save function:
def handle_event("save", %{"user" => params}, socket) do
{_, cset} =
socket.assigns.user
|> User.changeset(params)
|> Ecto.Changeset.cast_assoc(:users_details, with: &UserDetails.changeset/2)
|> Repo.update()
{:noreply, assign(socket, user_changeset: cset)}
end
And I really don’t understand what’s wrong, because the value in the database and in the template changes, but the error occurs in the terminal
[debug] QUERY OK db=0.1ms idle=1167.0ms
begin []
[debug] QUERY OK db=0.6ms
UPDATE "users" SET "email" = $1, "updated_at" = $2 WHERE "id" = $3 ["newEmail@gmail.com", ~N[2021-10-05 08:30:20], 1]
[debug] QUERY OK db=0.6ms
UPDATE "users_details" SET "first_name" = $1, "updated_at" = $2 WHERE "id" = $3 ["newFirstName", ~N[2021-10-05 08:30:20], 1]
[debug] QUERY OK db=19.2ms
commit []
[error] GenServer #PID<0.6447.0> terminating
** (Protocol.UndefinedError) protocol Phoenix.HTML.FormData not implemented for #Project.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, confirmed_at: nil, email: "newEmail@gmail.com", id: 1, users_details: %Project.Accounts.UserDetails{__meta__: #Ecto.Schema.Metadata<:loaded, "users_details">, first_name: "newFirstName", id: 1, inserted_at: ~N[2021-10-05 07:57:36], user_id: 1, ...> of type Project.Accounts.User (a struct). This protocol is implemented for the following type(s): Ecto.Changeset, Atom, Plug.Conn
Why does GenServer think I am passing the User structure when I explicitly call Ecto.changeset? And why is there no error in the template itself and everything is displayed correctly?
Thank you in advance.