 The What is New in Rails 5 track, I'm extremely proud to be part of it. I'm excited for all other talks today. I think this is a really cool release. So let's dive into cable boxes. So this was the first cable box I ever saw. And look, it's got a cable. I don't know if any of you are old enough to have seen one of these things. But this would sit and connect to your TV, and you'd be like, okay, to get to 33, I find that, and I've got to do the dial. But that's not the cable we're talking about, obviously. For this presentation, I made several high-quality 8-bit art, not 2-bit, not 4-bit, but diagrams throughout this presentation, you're welcome in advance. Here we see our intrepid user connecting to Rails through a cloud. Yeah, so again, you're welcome. I'm pretty good. So how can ActionCable sort of change this up? So what we're going to do is we're going to talk about the history of ActionCable and WebSockets. We're going to talk about what it is, what it's not. We'll talk about building blocks, like what actually, what code is there for you to use, and then some patterns. We'll also talk about deployment strategies, how to actually make use of this today. My name is Jesse Walcomont. You can, um, I'm J-WO on Twitter and the GitHub's. If you've got questions, comments on this talk, I don't think we're going to have time for Q&A, so tweet at me, um, and I'll do my best to get you an answer. So I found that the best way to look forward at changes that we're going to take place is to look back and to see where sort of we stand in this march of time. So let's start at our F5 refresh, or like our command R. So in general, like, this is how we would update a page for a lot of times. So like, checking your email was frustrating. You had to click refresh. And then you had to make sure that like your two meg of storage didn't get taken up by someone sending you like a 300 by 300 JPEG. And then you had to like call, because texting wasn't really a thing yet, you had to call your friend and be like, check your email, it is full. Kids today with your gigs upon gigs upon gigs of storage, you just don't understand. So other than that, like, if you're going to get a page to update itself, maybe you could just have it like auto refresh. So you could have like a meta tag that would say, hey, refresh yourself every three to ten seconds. Um, dredge report sort of did this for a long time, I think still does. And since sites being paid by the ad impressions, like, this is a pretty good story. You just leave your site up and it would just refresh, refresh, refresh. I don't know why that model didn't work. But this would be the code that would make that work. So by the time that like 2002, 2003 came along, we wanted better. And so we got polling. Polling would be in that time like Gmail, right? Like, Gmail came out and it's, hey, you've got two new messages. We didn't update the page. It, and at the time that's like, what? Okay, now this is in 2002, or 2012, excuse me, but DHH said, campfire to this day still uses a three-second poll. Chat was supposed to be the poster boy for WebSocket and some friends. Now, that's 2012, times have changed. I'm glad that we can move on, but this was DHH's view. He said, polling remains a great way to make your app dynamic. If you don't require sub-second responses, live updates in Basecamp are polling. So like, this works on a very large set of websites where you can just have it like every three seconds, fetch my new stuff. So there are apps that don't need like sub-second responses. Having your JS poll for changes on an interval is like an extremely good idea in many circumstances. So this can be what that looks like, you know, you jQuery pops up, you say set an interval, make an AJAX recall every three seconds, and sort of set it and forget it, but then we get to WebSockets, which are so hot right now. So I first saw like WebSockets be used with Push or App. And they're here, and it made everything very easy, like they took care of everything for you. So like you'd process an image in the background and then post to Pushers API when you're done, and your front-end listened to Pusher and like updated when it was done. So this came about as far as I can tell by RFC 6455 in 2011. It says basically it's two-way communication between the client and the server, and that the remote host has to opt in to the communication. That it can't just, whereas HTTP calls just go and are taken, right? But the client has to request a WebSocket, the server has to say yes. So some examples, socket.io made things pretty simple in node land to push updates from the server out to the client. Patrick Newkentze, patio 11, built a pretty sweet fake stock market. I don't know if you've played with this or not, but it is pretty sweet. So it sends trades out via WebSockets, or you can constantly ask via an API call, like which, like, do you have any new trades that have been made? But the thing is, is like, you'd have to do that on a loop. Is there any trades, and is there any trades? You're making a new connection every time, and when you're trying to do high frequency trading, which is what sort of it's all about, you want to get at the trade as soon as it possibly can. And so connecting via WebSockets was a way that you can actually get it almost as it happens rather than making a call in an infinite loop. So the trouble is, how can a server keep track of all these connections? Like scaling up in a big server can sort of work in a language like Elixir and others like it, but what about our dear friend Ruby? If every connection, like, lives, and there's got to be an object that's like listening for connections from server to client from client to server, like, that has to be taken up in memory, and Ruby loves its memory. So you're probably like, I'm uncertain about 2,000 connections, let alone 2 million connections. So with Ruby and with Rails, there's got to be a story about scaling out, not just scaling up, and spoiler alert, there is. So is the future just real time? Probably not. I doubt that we're going to default to building every feature with action cable, but I think it can add sort of pizzazz and fun and really fast updates. Like for certain apps that require that low latency, website cuts is how I would describe TreeChillSelfGood, my philosophy. So let's take a look at what action cable is and what's not. So if we know where the possible awards are, but we also know where the awesome is, we can decide if it fits in our tool belt. So first, let's start with the what it's not. In general, it's not just a silver bullet that'll make everything like super fantastic great awesome sauce. So let's talk about like what it's not. So it's very much made to work inside of Rails. I could see a future where it's lifted out, but for when do I seem we're not there yet? I don't consider this a bad thing, but it does sort of want to be in a request, or it wants to connect with a controller. It wants to be in Rails. That's fine, I mean it's not like people are going to NPM install, action cable. It's also not necessarily a step forward for Rails into more JavaScript integration. Like there is JavaScript here, but like it's, I saw this and I was like I think this makes sense. It's not, it is just a feature. It's the next J builder, it's the next turbo links. It's not the next asset pipeline. It's not the next active record. It's just a feature. So let's talk about what it is. So it's a solid feature. Like it works, it's fun, it adds value to your app. I don't think it needs to be any more than this, but like this is sort of the scope. It's a nice feature to have for Rails apps. So like turbo responsive or turbo links and JavaScript responses. It's a way to like snapify Rails. It's a way to make it faster. Like there is a certain wow factor where you've got like two windows up. You make a change on one, it like propagates to the other. Like people are, so like wow, that's cool. It's also easy and fun, which like big props on that. So why no chat apps? Like why did I specifically come here and say, we're not gonna talk about chat apps? So when I came up with the idea for this talk, I was somewhat dread, like I was dreading the talk that I might hear if I attended. I think it'd be about chatting between users, maybe like an intercom.io style integration, but there's so much more that we can do with sockets. Cuz chat apps are the hello world of web sockets. They don't add to, like they don't add anything. Like there are features where like if it's a chat app, you probably want a chat app, but just adding chat to an app doesn't make it awesome. And so as we show people, hey, you can use action cable, here's a chat app. It's sort of like, but that's not where the real value proposition is. Cuz most apps don't need chat between two different users. Like Facebook, Chur, another social network, maybe? Well, I implore you, when you go and you try this out, don't just add chat to your existing apps as a way to check out action cable. But some apps do need communication between the server and the client. Like if we're building unsocial apps, there's big wins on what action cable can get us. Use case number one, as I see it, is collaboration. So this can be as complete as a big Trello style where we're both editing the same document or the same card or somebody adds a card and it shows up on my page. Or maybe a price changes on a website, inventory changes, stuff like that. It'd be nice if I'm viewing everything if it did update, rather than later on on another page load. Use case number two, asynchronous tasks. So if you're implementing a task that the server needed to say like, that's all new data from a third party or something. Maybe it's something like create a PDF from an invoice. You'd likely throw it on an action job and pull for when that's complete. It's not easy. It's not rocket science either, but it's doable. But action cable can make that fun. Okay, so the first action cable beta. So again, more with the history and then we'll get to code, I promise. Okay, so last year, action cable was announced as vaporware. It was announced with a diagram, but no code. This is the diagram. Now, not too much later, July of 2015, we got our first look at the code. That's only a couple months, so as far as vaporware existence, that's not all that long, but it was a non-rails experience. Now, it was only version 0.0, but trying it out was a little bit rough. So there are no generators, no deployment story, no standalone, no in-app version. And again, this is version 0, and here I'm complaining about it. I was able to get it to work, but it was a pain, like sort of diving into the source code pain to try and figure stuff out. And that's not necessarily the rails way. So I'm glad it existed, and I bring this up to say that if you tried it then, and didn't like it, now is a much better experience. The core is still there, but it's got the nice sugar, too. So the current beta version, 5.0.0 beta 3, which syncs across rails versions, was released in February 2016, and I was sort of like this, true story. So it made all the things that I had enumerated about for this talk, like do this, don't do this. If you want unauthenticated users, you have to monkey patch this, and it made them all just go away. It was great, and I was happy. So finally some code. Let's talk about building blocks, so the modules. So what makes ActionCable ActionCable? There are four distinct modules. So the first is the cable. So this is the actual connection from client to server. So it's what is connected to. So it lives on, messages go back and forth without having to reconnect. So then you've got a channel. So you've got your cable, that's the actual connection. Then you've got a channel. The channel is sort of a room. It's what you listen for events. So a channel is on the rail side, and it has a stream name. They can be like all products, or it can be scoped down to a specific user, like cart underscore, like that user's ID. Broadcasting is sending information out from rails through the channel to the client. And then you have a subscription. Subscriptions on the client side. Generally this is just JavaScript. It doesn't have to be an ActionCable, it's JavaScript. And it's the client side. You listen and you receive data from the server. Let's dive into each of these. So the cable, the actual connection. My examples in these are going to be in JavaScript, not CoffeeScript. So you can easily make these go to coffee, like js.coffee, but these are going to be JavaScript. So what we do here is we require the ActionCable library, all the channels, and then we create like a big app object. If it doesn't exist. And then we slide the cable onto the app global object. So in general, like this is what exists, app.cable on your JavaScript side. On the rail side, we tell it to process sockets in process. So this is async at slash cable. This is sort of the easy way to do it. The slash cables configurable, but this is sort of assumed to be the convention that you'll use. That's the actual connection between the two. So let's look at channels. On the rail side, a channel is like a controller. So it groups sort of ideas together. So you might have a products controller, maybe an inbox, a stream that's like specific to that user of updates. Think about this as like on Facebook, maybe you've got a stream on the right for like all your updates of what people do, and then maybe you've got a stream in the middle for your news feed. So they group together. So each channel has a connection, and it inherits from application connection. So this is very much controller inherits from application controller. So here's where you would tell that this connection that you have a current user object. So identified by current user, enables you to use this later on. It enables you to be able to say that your channel is only for a specific user. And on line seven here, we see what happens when the channel is connected to. So when the channel is connected, we find the user. So user.findby, id of cookies.signed, user id. So we'll come back to this in a little bit, but notice that it's cookies.signed, not session id. So you don't have a session, but you do have cookies. But since you have cookies, this could be in application controller if you're using like has secure password, which you might do here. So you would say on line nine, cookies.signed of user id is the user.id. And then on line five, user.findbyid's cookie.signed. So you would switch from a session of user id to cookies.signed of user id. I have a device example later for like the 90% of you who are wondering how to do this with device. So let's talk about broadcasting. So here I am using an action job to broadcast out the message to a JavaScript channel. That'll send it up to the client. So line six shows how to send it out. So actioncable.server.broadcast. And then you give it a stream name and a hash. So that hash would be the data that's going to be sent up. That hash, you'll send it out as a hash. It'll be received later in JavaScript as just a JavaScript object. So this can be done anywhere. Rate tasks, action jobs, controllers, model callbacks, like anywhere in Rails has the ability to send out broadcasts, which is cool. Also here I am doing the actioncontroller.render which is super awesome. I think we're going to look back and see this as a very cool feature. We'll go into that a little bit later. Finally you've got a subscription. That's the JavaScript listener. So when you create a subscription it listens for all broadcasts for that channel. So when the server broadcasts a message it calls the received function and that's where you get your data. So app.product is equal to app cable subscriptions create and then you've got connected if you wanted to log that, disconnected if you wanted to log that and then received. Received is sort of a magic function like that's what you need to call it. That's when I broadcast from Rails up to JavaScript, that's what it calls. And then you can do whatever you want with that data. So here it's like data.product.id but you can do whatever you needed to with this. Here I'm saying let's find a product with the data.product.id of that ID and replace it with a template. So in this example Rails is sending up the updated template for that product and it's just going to re-render right on top of it. So let's walk through a standard action cable interaction. We'll start on the client side this time. So by requiring action cable the cable cables to the Rails cable. The browser then upgrades the cable connection to a web sockets connection. I mean the subscription subscribed. Connection connects. And then to start listening for updates you create a subscription with the received function. That's what gets called. So you can have many subscriptions in like many different places. So what I mean by that is like app.channel or app.cable.channel is this global thing. So anywhere in JavaScript you can access it. So it could be your standard jQuery style like listen for the event or it could be in React like on the component amount it could be in Angular it could be in Ember on set of controller like any of these things can create a subscription and start using it. So the subscription calls receive data when the subscription receives the data and that's it. This is a Tron DeLorean. I love Giffy. So let's talk about patterns like how we might set up for specific scenarios. First we'll talk about data updates. So this is what I basically call collaboration. But we can keep data in sync across tabs and users in sync. I'm sorry, not sorry. So here we're looking at a pretty sweet browser setup. It's got four tabs. Up in the top right is the cart button. That's a cart. And we're selling tennis balls. So those are tennis balls. So that's your add to cart button. I'm telling you, I'm pretty good. But we're looking at like four tabs because the middle two are like on this site because I don't know about you but I'll go to Amazon and I'll do a search and they'll be like open a new tab. Open a new tab. Open a new tab. And you'll see all of these open that I can flip through. So if we add the cart on tab three, there's not one item in our cart. But what about tab two? It's typically not updated, right? It's typically, sort of it was, it'll show whatever was on that page as it loaded but not update itself even though tab three updated itself. It's not a huge thing huge thing, but what could we do to make this experience even slightly better? So after the update happens, like in a controller or a job, you would broadcast a message. The message can be data or it can be a Rails rendered template partial for you to update with. So this is the application controller.render. So when I heard about application controller.render, I was basically like dancing the dance of joy. So I've wanted this for so long. The use case that I have for it is like creating reports. So each month you'd want to create reports using whenever, like a rake task. And I'd want to be able to use Wicked PDF to take HTML and convert it to PDF. But it's not in a request cycle. Like there is no request at that point. So I had to do some like weird things, man, to like make that work. But now it's easy. You can just render an entire part, like a partial or a page. You just hand it what locals you think this partial should have. And they can be the same partial that you would use if you're like rendering your cart or rendering out like a list of products. I think it's going to be really awesome. Here's how you could send out new cart partial to a current user only. So you would broadcast to cart underscore current underscore user dot ID. So that would be scoped to just that user. It would only go out on channels where that's subscribed, where you are that user. So it's not that like the cable has all of the message. It only has the messages that it's actually subscribed to. Here's the channel setup that would set up the stream. So the channel would have subscribed and it would say streamed from cart underscore current user. Both these have been on the rail side. So you've got broadcast to a channel. And then JavaScript listens for that message. So app cable subscriptions create cart underscore the current user ID. He receives the data, replaces up the template. Now Tab 2 is happy. You can also sort of hook into existing JavaScript libraries. So maybe like you change a graph, update some options. Can action cable be used to send messages to the server? Did something happen on the client? Yes, it can. So if you want to send a message to the server and then out to other clients, here's an example for you. So the example that I've got is like an HTML5 slides presenter mode. So imagine that this is like reveal.js and we're all looking at it. So you'd be looking at sort of like a read-only state. I'd have the ability to change the slides. And so what we would do is you'd add an event listener. So you'd add an event listener to the slide change. Now that's reveal specific. So all of this is predicated on your JavaScript libraries having hooks that you can tie into. But what gets sent from client to server when you say app.slidesnotification.advancedslide and then you send it some data. So the slides notification, that's the channel name. And then you've got a channel method on advanced slide and then you send it the data. So app.slidesnotification.advancedslide. So advanced slide is the method that JavaScript will call to tell Rails that something happened. So here we say app.slidesnotification is the app cable subscriptions. So this is setting up the subscription, the previous slide was using it. And so we say advanced slide. So that's the function that we called when we said app.slidesnotification.advancedslide. This does this.performslides data. Back on the Rails side, we have a slides channel. So the streams from slides, that slides stream is the name of it. So earlier, one, two, three. So on line six here we say perform, perform on slides and send it the data. That slides becomes line three here, stream from slides and calls the line six slides method. So that is what comes in from JavaScript back to Rails. So there's the broadcasting out and then the receiving message back. So line six here, slides of data, we're, I'm just going to say, ifcurrentuser.admin, admin, then action cable server broadcast, like broadcast it out again. So what's interesting about this is messages go from client to server. It's not peer to peer. So like this makes sense when we think about it. But if I want to, if we were all on a server, right, and I wanted to send a broadcast message out to all of you, I would not send it directly to you, I would send it to the server and the server would send it to you. And vice versa as you reply back. So let's talk about collaboration. So Trello, we talked about cards, like that's sort of what it would be. Pivotal tracker, also the cards. But then on GitHub, they do a neat thing where it's sort of complete with yes, no, you can merge with, Trev CI comes back. And then it updates all the other users viewing the page. So this is a neat way that if, if I like click and merge, it's going to other people viewing that page, remove the ability to merge. I think that that's the type of thing that we can very easily get huge wins out of with ActionCable. Finally, asynchronous tasks. So let's imagine that we have a system where we use like mechanize to go out and fetch the latest data. This can take quite a bit of time, so let's throw it in ActionCable job, or in ActionJob. So the first thing we do is we generate a channel. So each channel is going to have many streams based on like a UUID. So each task that we do would have its own stream. From the JS, post it up, give it the UUID that defines this job. You would then create a subscription on that stream with that UUID for when messages come back from Rails. Maybe you have a site search job that performs search with a UUID. So you have your stream that you broadcast, hey, I'm starting. And then snip, you do all the stuff. And then ActionCable server broadcast the stream that it's complete and along with the template. And yeah, let's go ahead and discuss chat. I read that there's this concept of iMessage on iPhones lock-in that people really love seeing the bubble like when people are typing, that it makes it feel sort of instant, that you're connected to someone, like there's an actual person that's actually typing right now. So, oh, come back, come back. So Aziz Ansari talks about this in modern romance. So he asked someone out, he saw the bubble, but then nothing, like the bubble just went away after a while. He never got a reply in the sad face for Aziz. But there's this sort of emotional thing with this. Okay, so what would you do? So you could listen for the key up event on a text area and then tell the server that you're typing in, that you're typing in the conversation between you and Taylor Swift. Then when the message is sent, you would stop the bubble and render the message text, and maybe you would handle if you haven't typed in a while. End of chat. Let's talk about deployment. So in-app mode is basically easy mode. Think of it like you'd use Sidekick, not inline jobs. So you're not doing Sidekick, it's just inline. It works, but scalability is a thing. So it can be done with only one server, no rescue Sidekick. You can just say that everything is inline, everything is async. So you would tell it, my QAdapter is async, and then my config, cable.yaml, async, async, async. Everything is done async, so that's just threaded. It connects to slash cable on the rail server, and generally can work pretty well, but if you've got more than one server, like you've got multiple dinos or whatever, then you want to use Redis. So you want to have server, server, Redis, and Redis will keep it in sync. Otherwise, everything is just going to be in memory on each server, and that's no good, because if I connect to one server, that's a physical connection you connect to another dino, we have to have some way that I can actually pass messages back and forth. Redis would be that. Standalone is basically hard mode. It's slightly more involved. It's the same scale as sort of moving from async to Sidekick. You connect via Redis. You've got to have an actual, like, sockets.domain.io, you've got to configure where it is so it knows how to connect more with a person. So our green person connects to rails, again, you're welcome. When you broadcast it, it sends the message to Redis. Action cable is listening for that, and then action cable sends it back out. So quick likes and gotchas. So what about miss messages? I don't think we know yet what this story sounds like, but I think we have to think about the idea that if I'm just sending update, update, update, update, and you miss some messages, you go offline. What does that look like? In a physical, like, it's a physical network connection to somewhere in the world. So you want to use ActionJob. Don't inline, like, just broadcast it out in your controller. Because it would have to send, like, somewhere along the world. Don't wait for that. Also no session, only cookies. So here is your device version. You're welcome. You have to configure your request origins to allow or disallow people to be able to connect to you. Fun fact, don't leave a trailing slash in the host, because it will not work. And finally, the config.cable.yaml default setup, this is what gets generated. The production URL for Redis says local host. You'll need to change that. So where do you go from here? So I've got a simple example that you can look at, joo slash inventory cable. There is also ActionCable examples. These are very good. There's documentation on this URL. But so ActionCable is part of the Rails standard, just like ActionController. Finally, I want to give some many thanks. So thanks to DHH for having the idea, announcing it, making it happen, like, this is very cool. The 42 plus contributors on the ActionCable project, you all rule also. And thanks to the Iron Yard for paying for me to come here, spend today with you. So we're hiring developers across the U.S. that want to learn how to teach, make the world better, change lives, improve diversity. So if you're interested, tweet at me, come talk to me. I'm J.R.W. Thank you very much.