Best Practices from LiveBeats App

This is a thread to note down things/best practices encountered in LiveBeats App as I explore the source code.

Found this usage of rescue/1

I’ve been meaning to handle Ecto errors myself. So this comes in handy for next time.

35 Likes

Nice exercise @TwistingTwists

3 Likes
Who is current user in liveview app ? (even during redirects) More than just :fetch_current_user plug

https://github.com/fly-apps/live_beats/blob/master/lib/live_beats_web/controllers/redirect_controller.ex#L9

This has conn.assigns.current_user - without worrying that current_user might not exist.

above is possible because of plug :fetch_current_user here → https://github.com/fly-apps/live_beats/blob/master/lib/live_beats_web/controllers/redirect_controller.ex#L6

6 Likes
OneLiner For loop

https://github.com/fly-apps/live_beats/blob/master/lib/live_beats_web/live/live_helpers.ex#L494

Never seen a for loop like this before.

Practical render_slots

https://github.com/fly-apps/live_beats/blob/master/lib/live_beats_web/live/profile_live.ex#L22

Message passing other component from present one - JS.push

https://github.com/fly-apps/live_beats/blob/master/lib/live_beats_web/live/profile_live.ex#L25
“switch_profile” is in player_live.ex
https://github.com/fly-apps/live_beats/blob/master/lib/live_beats_web/live/player_live.ex#L208

Pattern Matching - via two variables in function - elegant

matching if current user is same as profile user or any other case.

https://github.com/fly-apps/live_beats/blob/master/lib/live_beats/accounts.ex#L93

7 Likes

I think I should write @docs in a forked repo instead, no?

4 Likes

First of all, thank you for this initiative!

https://github.com/fly-apps/live_beats/blob/master/lib/live_beats_web/live/live_helpers.ex#L494

Never seen a for loop like this before.

I’d recommend to post a “permalink” to the line in the commit. That file was changed 7 hours ago. And looks like the link doesn’t point to the place you meant to.

9 Likes

Protip: if you press Y while seeing a github file it replaces the url at the address bar with a permalink so you can copy that instead of scrolling and clicking copy permalink

12 Likes

Will take care.

Added comments in this forked repo for consistency!

1 Like

Excellent thread. Pinging @slouchpie so we can comb through this lots of good nuggets!

2 Likes
Explain for loop :

for a for {key, %{metas: metas}} <- presences, into: %{} do

what does into: do?

as explained by @kartheek - from elixir-lang

must remember : A comprehension is made of three parts: generators, filters, and collectables.

1 Like

it collects into %{} in this case

The codefrom live_beats app is transforming presences - adding users and meta to every key in the presences. Final result will be %{key1 => %{metas: <..>, user: <..> }, key2 => %{metas: <..>, user: <..> }}

2 Likes
Simple GenServer Implementation

Songs Cleaner

1 Like
put_change pattern for validation and casting in Ecto

see this file for put_user, put_stats etc

2 Likes

Can someone explain this link component?

<.link> defined here has a method={:delete}

which is using this definition here (as I understand so far) .

  1. How does this :delete work?
  2. do we need it even after we specify a call to :sign_out in href?

Worth noting nested for loops and :reduce / :uniq options too

# psuedo, may be incorrect
for bar <- foo, bazz <- bar, !is_nil(bazz) && !is_nil(bar), reduce: [], uniq: true do
 acc -> acc ++ [bar + bazz]
end

execJS

This function executes rendered JS commands

Check out the Phoenix.HTML docs for Link.link/2– You can override the default (:get) link method. You can also provide a data-confirm attribute to prompt the user before following the link. This is all ancient UX stuff that you get when you include phoenix_html.js. :slight_smile:

Almost certainly, but take a look at router.ex to be sure. You don’t want to put destructive actions behind a GET method (especially a public one) otherwise any request to the path will trigger the destructive action. Imagine a search engine spidering your delete links– it’s not ideal.

7 Likes
easier config management - especially - when you have a lot of configs

Config management - see examples mentioned above the code

1 Like
attach function in LiveBeats - needs explanation

defined here

used here

I do read the documentation in the cdoe. But what does attaching two modules mean? I see the code is using :telemetry to perform attach and execute handle_execute.

I am not well versed with :telemetry hence unsure about whats’ happening.

handle_execute broadcasts messages. via PubSub. Then why do we need telemetry?

@mcrumm @chrismccord please?

1 Like

Going through this LiveBeats code has been very helpful!

I have a question on memory management. For assigns created in a mount function, it’s simple to use temporary_assigns to clear data that doesn’t need to be tracked.

But what happens when within a LiveView, you create assigns in your HEEX template? For example, within the ProfileLive render function, there is the following code:
<.icon name={:code}/>

.icon is just a standard Phoenix component. Obviously it’s trivial in the case, but is the name assign now in memory being diff tracked with no way of having it cleared from memory since it wasn’t set in the mount function?

Reading through the docs now, my understanding is that it is diff tracked (and hence saved in memory).

So maybe for big chunks of data that don’t need to be tracked, best practice is to set in a mount function (and release with temporary_assigns) or pass it as a slot?