LiveView generator :show -- record doesn't show up when assigning current_user in mount

Hello All.

I used the phx.gen.live generator to scaffold up a context and table, etc.

I also have auth in the application (based on phx.gen.auth).

I put the generated live routes in the :require_authenticated_user pipeline. The generator gives me a :show live_view, and links to that live_view in the :index template

<span><%= live_redirect "Show", to: Routes.boat_show_path(@socket, :show, boat) %></span>

The call is handled in the :show live_view in handle_params :

 def handle_params(%{"id" => id}, _, socket) do

    {:noreply,
     socket
     |> assign(:page_title, page_title(socket.assigns.live_action))
     |> assign(:boat, Structures.get_boat!(id))}
  end

Since I need the current_user in order to authenticate the route, I added it to the socket (assign_current_user is in the live_helpers.ex file — using the assign_new function) in the mount.

def mount(_params, session, socket) do
    socket = assign_current_user(socket, session)

    {:ok, socket}
 end

I get a KeyError stating it cannot find the specfic record:

##### KeyError <small>at GET</small> <small>/boats/1</small>
# key :boat not found in: %{__changed__: %{current_uri_path: true, current_user: true}, current_uri_path: "/boats/1", current_user: #Baseline.Accounts.User<__meta__: #Ecto.Schema.Metadata<:loaded, "users">, avatar_url: "/uploads/6ab0c1ff-e501-4c3e-a636-ff60c423cf1f.jpg", bio: nil, confirmed_at: nil, email: "user1@example.com", full_name: "John Doe", id: 1, inserted_at: ~N[2022-06-25 21:36:59], updated_at: ~N[2022-06-25 21:37:48], username: "user_number_1", website: nil, ...>, flash: %{}, live_action: :show, socket: #Phoenix.LiveView.Socket<assigns: #Phoenix.LiveView.Socket.AssignsNotInSocket<>, endpoint: BaselineWeb.Endpoint, id: "phx-FvwEwArWOvo60Qmi", parent_pid: nil, root_pid: nil, router: BaselineWeb.Router, transport_pid: nil, view: BaselineWeb.BoatLive.Show, ...>}

What am I missing.

All help appreciated; thanks in advance.

DJ

Further to this, if I delete the current_user assignment in the mount, the record shows up, but I get a similar error stating it cannot find :current_user.

Thanks again.

It’s telling you that you’re trying to fetch boat from the assigns but it is not there. Most likely you are referencing a @boat assign somewhere in one of your templates without a corresponding assign(socket, :boat, boat). Either that, or you are calling socket.assigns.boat in a callback

Thanks for the reply.

I think the assignment of :boat occurs in the handle_params

If I understand it correctly - handle_params fires after mount – so if I assign current_user in the mount, I have the current_user record but no boat. If I remove the current_user assignment in the mount, I get the :boat record, but I get the same KeyError saying no :current_user (which I believe it needs since the route requires authentication).

Would you be able to post the full code of mount and handle_params, as well as the parts of the templates where these are called?

handle_params is invoked after mount, before render.

What do you mean “the record shows up”? It actually renders on the page?

I think it’s more likely that :current_user is just the first to fail, not that you’ve traded it for :boat. You might be calling @current_user in a template. It’s not required that you assign :current_user to the socket for authentication, you just need to check for the current user at minimum. You only need to assign :current_user if you depend on it for rendering the html. You will get the key error if you’re trying to access it somewhere and it doesn’t exist.

Sharing more code will help illuminate the problem I’m sure :slightly_smiling_face:

Thanks again.

What do you mean “the record shows up”? It actually renders on the page?

No, they are not rendered, but in the KeyError message, the current_user is not found (I deleted from the mount), then the correct boat record is displayed in the error. Similarily, in the KeyError message in my original post – the current_user record is shown in the error message, but the :boat record is not found.

Would you be able to post the full code of mount and handle_params, as well as the parts of the templates where these are called?

Yes. Those methods are included in the original post. I also included the link from the index page (a generated table of records) that invokes the :show.

One more thing I will add. When I live_redirected to the :index page from “/”, I also got the KeyError for :current_user — which was solved by assigning the :current_user in the mount (via the assign_current_user/2 method shown). The :current_user is only displayed in a header component, so I am unsure why this link is looking for it (which is why I thought it must be for authentication).