Abeltensor
Abeltensor

Reputation: 182

phoenix presence fetch/2 override

I want to be able to pass user meta data through the :meta map in phoenix presence to access it from the JavaScript side. More specifically, I want to be able to push image file paths (strings) and have them associated with each user in my presence list. The documentation gives this example for overriding the fetch/2 function to add User model data into the :meta map:

def fetch(_topic, entries) do
  query =
    from u in User,
      where: u.id in ^Map.keys(entries),
      select: {u.id, u}

  users = query |> Repo.all |> Enum.into(%{})

  for {key, %{metas: metas}} <- entries, into: %{} do
    {key, %{metas: metas, user: users[key]}}
  end
end

However, when I make the appropriate changes for my User Model, I get errors regarding the variable u and the from/2 function as well as cannot use ^Map.keys(entries) outside of match clauses.

I went looking for examples of people trying to do similar things and was unable to find anything on github that is similar to what I am attempting here.

Anyone have any idea how I can go about restructuring the fetch/2 function so that it will work properly? I have a basic user model with 3 fields, email, password, and icon/avatar image.

Upvotes: 2

Views: 381

Answers (2)

Abeltensor
Abeltensor

Reputation: 182

I found out what my problem is. Basically, the metas map in my application is not always populated with the value that I want it to be. In this case, it doesn't always have the user.id inside of it. Apparently, when a user joins the channel, the fetch function is called at least 4 times. If I inspect the fetch function's entries map after running Map.keys on it, it returns:

["1"]
["1"]
[]
[]

So basically in two out of the four instances where the fetch function is being called, my channel app is returning 2 empty values for the key and when those empty values are put into the query it causes an error.

Unfortunately, this means that there is an error some where else in the application that causes this empty value to be passed to my fetch function; most likely in the JavaScript or my channel modules.

I'm going to have to rebuild this app from scratch, so I guess that means this question is closed. Alternatively, I could put in some error handling in the form of a guard or pattern matching statement to protect against these empty values, but I think it would be better in the long run if I just restart.

Upvotes: 1

Steve Pallen
Steve Pallen

Reputation: 4507

You need to import Ecto.Query to use the from macro. This is done in your web.ex file so when you use MyApp.Web, :controller, you have it imported through the quote block in web.ex. However, you need to do this manually in other modules.

Add the following to the top of your presence module like this

defmodule MyApp.Presence do
  use Phoenix.Presence, otp_app: :my_app,
                        pubsub_server: MyApp.PubSub
  import Ecto.Query
  # ...
end

Upvotes: 0

Related Questions