Refactoring for poll chats

We need a way to be able to specify which chatroom to connect to for our polls-specific chat. To do that we'll need to start specifying the chatroom (we'll use that as part of the topic to connect to). We'll start by placing a data attribute on our chat-window in lib/vocial_web/templates/shared/_chat.html.eex that we will reference later in our chat.js file:

<div class="chat-window container well" id="enable-chat-channel" data-chatroom="<%= @chatroom %>">

We'll need to actually pass a value to that that will enable us to reference @chatroom since right now we're not setting that anywhere. We'll also need to hop out to our lib/vocial_web/templates/poll/show.html.eex and set that as part of the call to render:

<%= render(VocialWeb.SharedView, "_chat.html", messages: @poll.messages, chatroom: @poll.id) %>

This will currently break, as we're not including messages as a part of our preloads for our query, so we'll also need to hop over to lib/vocial_web/votes/votes.ex and change our get_poll/1 and list_polls/0 functions:

  def get_poll(id) do
Repo.get!(Poll, id)
|> Repo.preload([:options, :image, :vote_records, :messages])
end

def list_polls do
Repo.all(Poll) |> Repo.preload([:options, :image, :vote_records, :messages])
end

We'll want to do the same in lib/vocial_web/templates/page/index.html.eex as well (this one being set to "lobby" instead of the poll's ID):

<%= render(VocialWeb.SharedView, "_chat.html", messages: @messages, chatroom: "lobby") %>

Next, we'll need to change the JavaScript code in assets/js/chat.js to use this new data attribute. We'll start off by getting that information out and putting that in our connect function, and we'll also change what channel we join by default:

// Get the chatroom that we're supposed to connect to
const chatroom = document
.getElementById("enable-chat-channel")
.getAttribute("data-chatroom");
// Create a channel to handle joining/sending/receiving
const channel = socket.channel("chat:" + chatroom);

Finally, we'll modify our join function for the Chat Channel module (in lib/vocial_web/channels/chat_channel.ex). We'll also need to modify our handle_in function to also be able to pull the poll_id (or lobby) out of the socket:

def join("chat:" <> _poll_id, _payload, socket) do
{:ok, socket}
end

Nothing special here! The last piece we need to do is flesh our handle_in function. It's mostly the same, but we'll start by pulling the poll_id out of the socket's topic (since it goes in the format of "chat:(poll ID or lobby)".

poll_id = case socket.topic do
"chat:lobby" -> nil
"chat:" <> id -> id
_ -> nil
end

Finally, we need to modify our create_message function in our with statement to pass in the poll ID:

with {:ok, _message} <- Votes.create_message(%{author: author, message: message, poll_id: poll_id}) do

The end result is that we should now have chats that are separate between the lobby and specific polls; we finally have that social edge to our application that we wanted to build! This is a pretty great portion of functionality and the kind of thing that allows us to really elevate our application!

Let's take a look at what the chat window looks like embedded in a Poll view, which should pretty closely match our original mockup:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset