"protocol Enumerable not implemented" error, what am I doing wrong?

Hi,
long time lurker here, finally started working with Elixir and Phoenix on my side project, enjoying it so far but as expected, I stumbled upon a problem and I hope someone could help me out.

So, I have two tables, users and profiles with has_one association between them. I would like users to have the ability to edit their profiles from their user accounts, so there should be a route /account/profile/ where they can edit and update their profile.

With my current code I’m getting this error

protocol Enumerable not implemented for %Project.Accounts.Profile{meta: #Ecto.Schema.Metadata<:loaded, “profiles”>, id: 5, inserted_at: ~N[2020-11-29 15:50:06], name: “First Profile”, state: nil, updated_at: ~N[2020-11-30 13:16:49], user: #Ecto.Association.NotLoaded, user_id: 11} of type Project.Accounts.Profile (a struct)`

From my router.ex

get “/account”, AccountController, :index
get “/account/profile”, ProfileController, :edit
put “/account/profile/update”, ProfileController, :update

ProfileController.ex

def edit(conn, _params) do

user = conn.assigns.current_user
profile = Accounts.get_user_profile!(user)
changeset = Accounts.change_profile(profile)
render(conn, "edit.html", profile: profile, changeset: changeset)

end

def update(conn, %{“profile” => profile_params}) do

 user = conn.assigns.current_user
 profile = Accounts.get_user_profile!(user)

case Accounts.update_profile(profile, profile_params) do
  {:ok, profile} ->
    conn
    |> put_flash(:info, "Profile updated successfully.")
    |> redirect(to: Routes.profile_path(conn, :edit, profile))

  {:error, %Ecto.Changeset{} = changeset} ->
    render(conn, "edit.html", profile: profile, changeset: changeset)
end

end

Accounts.ex

def get_user_profile!(user) do

Repo.get_by!(Profile, user_id: user.id)

end

edit.html.eex

<%= form_for @changeset, Routes.profile_path(@conn, :update, @profile), fn f -> %>
<%= if @changeset.action do %>


Oops, something went wrong! Please check the errors below.



<% end %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= error_tag f, :name %>

<%= submit "Save" %>

<% end %>

I’m getting the error when I try to open /accounts/profile :edit path but if I remove @profile from the form in edit.html.eex file, then that page works but I get the same error when I click save to update the profile.

Can anyone help?

when calling Routes.profile_path you should pass the id, not @profile. Most probably you need to do just: Routes.profile_path(@conn, :update, @profile.id).

1 Like

Your route doesn’t have any placeholders (like :id) so it should be called as Routes.profile_path(conn, :edit); route helpers always take a trailing argument that’s a list of query parameters, so the error is happening when the function tries to traverse the list.

2 Likes

you’re right, i completely missed the fact that @KiKi is not using the resources helper.

That’s it, it worked. Thanks a lot!