Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Intro to Phoenix Part III

Intro to Phoenix Part III

Using channels in Phoenix

Jessica Goulding

January 09, 2017
Tweet

More Decks by Jessica Goulding

Other Decks in Technology

Transcript

  1. WHAT WE HAVE COVERED SO FAR… ▸ Created new project

    ▸ Reviewed Generators and what they gave us. ▸ Generated post model, controller and view ▸ Added Ex-Machina for test data ▸ Built Authorization from scratch ▸ User Model/Controller ▸ Registration Model/Controller/View ▸ Session Model/Controller ▸ Cleaned Up Views to show current user and log-out
  2. ADDING PRESENCE ▸ What is Presence? ▸ Run command `mix

    phoenix.gen.presence` ▸ Add into our application as notes suggest PRESENCE & CHANNELS BY @JESSICAEWEST Provides Presence tracking to processes and channels. This behaviour provides presence features such as fetching presences for a given topic, as well as handling diffs of join and leave events as they occur in real-time. Using this module defines a supervisor and allows the calling module to implement the Phoenix.Tracker behaviour which starts a tracker process to handle presence information.
  3. USER SOCKET MODULE ▸ What is a User Socket? ▸

    What do we get out of the box? PRESENCE & CHANNELS BY @JESSICAEWEST # lib/retrodoc/endpoint.exsocket "/socket", Retrodoc.UserSocket **Poll audience about sockets** Socket: In a web context, a socket is an open connection between a user’s browser (the “client”) and our app (the “server”). With a typical web app, the client makes an HTTP request (e.g. GET /home) to the server, the server returns a response (e.g. the HTML for the home page), and the connection is closed. A socket allows the client- server connection to remain open so the client and server can continue to exchange messages as long as the user remains on the page. Our User Socket Module: When a browser opens up a socket connection to our app, the UserSocket’s job is to identify which “user” that is, usually by some means of authentication. Conceptually, this is similar to how a controller in an MVC app identifies and stores the current_user.
  4. MODIFY USER SOCKET MODULE ▸ Modify our existing connect method

    to bring in a user and assign it as such. PRESENCE & CHANNELS BY @JESSICAEWEST # web/channels/user_socket.ex What this does is when our JavaScript connects to the socket Phoenix will send its params to the connect function in our UserSocket module, where we can pattern match on the user and assign it to the socket for reference later on.
  5. MODIFY USER SOCKET MODULE ▸ Uncomment line 5 PRESENCE &

    CHANNELS BY @JESSICAEWEST # web/channels/user_socket.ex channel "room:*", Retrodoc.RoomChannel Sockets are allowing us communicate with one another on this website, channels allow us to hone in to specific areas. For our purposes, we are using the Sockets as the parent document for retrospectives and channels for the specific week of that retrospective. The asterisk here after rooms allows us to have as many rooms as we would like!
  6. ADDING IN CHANNELS PRESENCE & CHANNELS BY @JESSICAEWEST # web/channels/room_channel.ex

    Here, Presence makes an important appearance. When we call room.join("room:january") in our JavaScript, this module’s after_join function will call Presence.track to start tracking that user’s presence in this room. socket.assigns.user is the user’s name which we stored earlier in the UserSocket’s connect function. And we can attach additional metadata (online_at) such as when the user first joined the room. To keep track of this user amongst others, we push the current state of who else is online (Presence.list) back to the user via a "presence_state" event.
  7. DISPLAYING PRESENCE IN THE BROWSER ▸ Adjust logic in the

    view to show channels for logged in users. ▸ Add span and id to show username ▸ Let’s do some Javascript! ▸ Grab information from that span id we just created for socket connection. PRESENCE & CHANNELS BY @JESSICAEWEST Let’s import the Socket and Presence JavaScript that comes with Phoenix, which we’ll make use of. Using the view displaying the user’s name in the span id, we grab that name here, pass it to a new Socket connection, and connect. BOOM.
  8. ADDING VIEW TO SEE USER PRESENCE & CHANNELS BY @JESSICAEWEST

    # web/static/js/app.js Let’s walk through what we are doing here. formatTimestamp: makes our server-generated timestamps (e.g. :os.system_time(:milli_seconds)) into a format that’s human-readable and in the browser’s time zone. Presence.list is wicked. A user can have multiple presences (sent as metas with Phoenix). IE online from two browsers through lets say their phone and computer. What we are doing with the listBy function is returning a JavaScript object with the user’s name and when they were first detected online. render updates our list of users to display all online users. We’ll use this for whenever a user joins or leaves this room (retrospective week). Feels a lot like a Google Doc, eh?
  9. ADDING VIEW TO SEE USER (CONTD) PRESENCE & CHANNELS BY

    @JESSICAEWEST # web/static/js/app.js Channels… We are using JS to connect to our room:january. Right now we are only doing one, but ideally in future cases we would have this as a variable we pass in through. We need to handle two events as far as Presence is concerned. "presence_state" and “presence_diff” Presence State: when the server sends us the state of everyone online, which happens when we first connect and if we ever disconnect. Presence Diff: the server will send when someone joins or leaves and contains the difference we need to adjust for. In both cases, Phoenix’s Presence JavaScript has special functions to do the heavy lifting for us: both syncState and syncDiff will set our presences object to the current state of who’s online, which we then render as HTML for display.
  10. NOW WE CAN SEE OUR USERS! ▸ With everything we

    have added, now we can see users online and the timestamp associated! PRESENCE & CHANNELS BY @JESSICAEWEST
  11. ADDING POSTS ▸ Now that we have presence enabled with

    users, we need to implement users publishing messages. In our case, feels. PRESENCE & CHANNELS BY @JESSICAEWEST # web/channels/room_channel.ex We need to add a function to the RoomChannel module to handle new chat messages. What we’re doing here is listening for messages of the type "message:new" and broadcast!-ing them to everyone connected to the current room (including ourselves) after adding some additional metadata like who posted the message and when. This however, does not handle it alone. We need… MOAR JAVASCRIPT
  12. MOAR JAVASCRIPT ▸ Now that we have presence enabled with

    users, we need to implement users publishing messages. In our case, feels. PRESENCE & CHANNELS BY @JESSICAEWEST # web/static/js/app.js We need to wire up the <input> to listen for the Enter key (keyCode 13) and use room.push() to send whatever the user’s typed to the server. Once we receive a message from any user (including the current one), the server will send it back out (with the user’s name and message timestamp as metadata) over the socket as a "message:new" event. We’ll listen for those messages client-side and upon receiving one, build a <li> with the message data and append it to our message list.
  13. MOAR JAVASCRIPT(CONTD) ▸ Lets push messages up the list as

    they come in (similar to a chat room). PRESENCE & CHANNELS BY @JESSICAEWEST # web/static/js/app.js Now we set the messageList.scrollTop to its maximum value (the very bottom) to ensure that new messages are always displayed, pushing older messages up out of immediate view.
  14. THAT’S A WRAP! ▸ What did we cover? ▸ Adding

    in Presence ▸ Working with User Sockets ▸ Working with Javascript and Presence to display user data PRESENCE & CHANNELS BY @JESSICAEWEST
  15. PROJECT NEXT STEPS ▸ Pushing to server ▸ Adding multiple

    columns within one channel ▸ Adding reactions to user posts ▸ Adding multiple channels per week PRESENCE & CHANNELS BY @JESSICAEWEST
  16. HELPFUL MIX COMMANDS ▸ Running your server ▸ mix phoenix.server

    ▸ Looking at your routes ▸ mix phoenix.routes ▸ Migrations ▸ mix ecto.drop/mix ecto.create/mix ecto.migrate PRESENCE & CHANNELS BY @JESSICAEWEST
  17. PRESENCE & CHANNELS BY @JESSICAEWEST HELPFUL PRY COMMANDS ▸ Running

    your server in Pry mode ▸ iex -S mix phoenix.server ▸ Running your tests in Pry mode ▸ iex -S mix test --trace