Populating virtual field in preload

I got a problem with one virtual field. I have an association from chat to chatuser, which has an association to chatmessages. I got an other table which has a relation to the chatmessage, an user_id and the flag viewed. The chatmessage has a virtual field viewed. I populate it over the changeset in my chatmessage controller. When I request one chat the chatuser with his chatmessages gets preloaded. In this case I am not able to populate the virtual field.

My preload code in my chat controller is as followed:

defp preload_associations(chat, params) do
  updated_since = Map.get(params, "updated_since", "1970-01-01T12:00:00")
  chat_user_query = from u in Chat.ChatUser,
  where: u.updated_at > ^updated_since
  chat_message_query = from m in Chat.ChatMessage,
  where: m.updated_at > ^updated_since

  Repo.preload(chat, [
    [chat_users: {chat_user_query, [[chat_messages: {chat_message_query, [:video, :attachment]}]]}]

The parameter updated_since allows me to reduce the response.
The problem now is, that I have no Idea how I can populate the virtual field viewed in chat_messages. I could pass conn.assigns.user_id to the methode and use it somehow in my chat_message_query but I have no idea how to do this. Has anyone an approach for me?

If you feel like this is a field that should be updated in a query, maybe it should not be virtual. But anyway updating a virtual field is the same as updating any field in any struct, the only wrinkle here is your multiple-levels of nested lists.

A first approximation - (untested)

Enum.map(user.chat_users, fn user -> 
  Enum.map(user.chat_messages, fn message -> %ChatMessage{message| viewed: true} end)
1 Like

Hm, so after the preloading taking the result and viewed: true -> viewed: my_function(user_id, message.id)
Seems like a possible way to deal with my problem. Will try this one. Thanks :slight_smile: