Skip to content

Conversation

@Kavignon
Copy link
Contributor

@Kavignon Kavignon commented Feb 9, 2025

Summary

In this PR, we changed things by allowing application users to navigate all the existing chat rooms. Other than seeing the different available chat rooms, the application isn't that interesting at the moment.

Screen.Recording.2025-02-09.at.1.55.52.PM.mov

Primary focus targets from lessons

What are function components, and when do we use them?

In this lesson, we learn about function components. You can see this from the official docs below.

any function that receives an assigns map as an argument and returns a rendered struct built with the ~H sigil:

Source: https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html

We define the room_link/1, which can represent the link to a chat room. As a function component, it allows custom logic to be written as dedicated functions that will render a HEEX struct. This significantly reduces the amount of logic in the main HEEX template.

In the live view page, I'm using the function attr/3

From the docs, we can see the following:

An attribute is declared by its name, type, and options.

It allows the annotation of the expected components within function components with their dedicated information. We don't have to do so, but it removes a layer of protection that LiveView can provide. By doing so, we're telling LiveView, for instance, that :active is supposed to be a boolean. Furthermore, the opts argument gives additional protection through the different options it supports. For instance, by using :required, if we forget to provide this attribute, we will be getting a compile warning from Phoenix.

Extracting content from request parameters

The mount callback receives three arguments: the request parameters, the session, and the socket.
The parameters can be used to read information from the URL

From the docs: https://hexdocs.pm/phoenix_live_view/welcome.html#parameters-and-session

We can produce verified routes using the p sigil (~p).

Use of the sigil_p macro allows paths and URLs throughout your application to be compile-time verified against your Phoenix router(s)
Will be verified against your standard Phoenix.Router definitions
Unmatched routes will issue compiler warnings
interpolated ~p values are encoded via the Phoenix.Param protocol.

Docs: https://hexdocs.pm/phoenix/Phoenix.VerifiedRoutes.html

So, during mounting, we grab the parameters passed by the caller. By leveraging ~p in room_link/1, we can generate a verified route for each of the chat rooms available in the database. Since we added a new route for chat rooms, specifically in the router, it will not produce a warning.

So here, we extend the default behavior of the chat room page. All chat rooms are listed by default. Using the verified routes, we can navigate to any one of those rooms during the page's mounting, or we can load the first room found in Postgres.

If this were an actual application, there would be some issues here, such as running Repo across all the possible rooms in the DB server.

Avoid dropping the web socket and wasting resources (and end-user time)

So, when we mount the page, we mount twice, once while waiting for a web socket and once the web socket is connected. When using href for navigating, we can see the following in the docs:

Uses traditional browser navigation to the new location. This means the whole page is reloaded on the browser.

https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#link/1

This is wasteful because it'll drop the web socket connection and loads the new chart room with a new web socket connection.

By using the function component link/1 with the navigate attribute

Navigates to a LiveView. When redirecting across LiveViews, the browser page is kept, but a new LiveView process is mounted and its contents is loaded on the page. It is only possible to navigate between LiveViews declared under the same router live_session. When used outside of a LiveView or across live sessions, it behaves like a regular browser redirect.

https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#link/1-attributes

So, we can preserve the existing connection within a live view session and move from one chat room to the next.

live_session/3 allow routes defined with live/4 to support navigate redirects from the client with navigation purely over the existing websocket connection. This allows live routes defined in the router to mount a new root LiveView without additional HTTP requests to the server.

https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.Router.html#live_session/3

Pushing automation with Docker forward

Since I'm working with a script that cleans up my Docker environment in dev, it removes any changes made in the database service container. To remedy the situation, I added Faker as a dependency. After mounting, I added a seeding mix task that the application container could use to seed the Chatroom table with faked data.

With the seeding script, we can continue adding and evolving it over time to ensure nothing isn't anything missing. For now, it's straightforward and looks 'bad' because it doesn't look like actual chat room names. For the sake of being fast, that isn't something I'll care about, especially since this is a follow-along class.

Nothing would stop me or anyone in the future from making a PR that makes the data look more human-friendly.

@Kavignon Kavignon self-assigned this Feb 9, 2025
First, the run function wasn't being recognized. I thought it was valid (came from AI model recommendation) and the code was functioning so I didn't think much more of it. Another thing that needed to be fixed was updating the Slax Dialyzer configuration regarding its Persistent Lookup Table (PLT). It was missing some information on the expected behavior for Mix.Task and was unable to infer whether the task was correctly implemented or not. I extended the project's definition with mix to ensure dialyzer wouldn't be confused anymore.
Prior, I had created a custom task for seeding data in Postgres. An issue that rose was that when the Docker container is up, it doesn't mean that the application is running when executing its entrypoint. From research, I saw that the correct practice was to use priv/repo/seed.exs as the task seeding the DB. Furthermore I also found the function to invoke to ensure that the app is running prior to seeding.
@Kavignon Kavignon merged commit 01e707a into main Feb 15, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants