List

Exploring the Power of Turbo Streams and ActionCable

Exploring the Power of Turbo Streams and ActionCable

by Kevin Liebholz

In this session titled 'Exploring the Power of Turbo Streams and ActionCable' presented by Kevin Liebholz at RailsConf 2023, participants embark on a coding journey through the magical realm of Turbo Streams and ActionCable, highlighted through a real-time tic-tac-toe game. The talk creatively intertwines elements from the fantasy series, 'The Inheritance Cycle' by Christopher Paolini, using the characters Eragon and Saphira against the dark king Galbatorix to frame the programming concepts.

Key points discussed during the presentation include:

  • Introduction to Real-time Technologies: The speaker begins by discussing the importance of real-time interactions through web sockets, differentiating it from traditional HTTP requests where the client must request updates from the server. Web sockets maintain an open connection for instant data transmission.

  • Understanding Action Cable: Action Cable is described as the magic of Rails for implementing web sockets smoothly within applications, providing both client-side and server-side frameworks in Ruby.

  • Turbo Streams Overview: Turbo Streams are introduced as a higher-level abstraction built on Action Cable, which allows real-time DOM updates with fewer codes. The talk emphasizes how it simplifies broadcasting messages and rendering updates automatically when server messages are received.

  • Building the Tic-Tac-Toe Game: The practical demonstration starts with creating a skeleton for the tic-tac-toe game, defining models for players and games. Various constraints are added to increase difficulty, demonstrating related Turbo and ActionCable features in action. This also helps visualize how signaling works between the player actions.

  • Implementing Constraints and Notifications: Throughout the game-building process, three main constraints are mentioned:

    • The requirement of exactly two players to start a game.
    • Restricting connections to prevent unauthorized players (like a henchman) from joining the game.
    • Ending the game and notifying players when one leaves. Each of these constraints is implemented with practical coding examples, showcasing broadcasters and connection handling techniques.
  • Conclusion and Acknowledgments: The session wraps up with a triumphant conclusion of the coding project that involves engaging storytelling intertwined with technical learning. Liebholz expresses gratitude to the RailsConf organizers and encourages discussions post-event, highlighting the importance of community in programming.

The main takeaways from the presentation include a deeper understanding of using Turbo Streams and ActionCable for real-time application features, along with an example of how to construct these functionalities systematically. The engaging narrative makes learning these technical concepts more relatable and enjoyable.

Dive into the world of Turbo Streams and ActionCable with the Dragon Rider Eragon and his majestic dragon, Saphira, as we build a real-time tic-tac-toe game. We will utilize Turbo Stream broadcasting and ActionCable customization to create the game for our heroes, adding constraints of rising difficulty one after the other. Are you an advanced coder? Or are you a beginner? As long as you are looking to explore new applications of Hotwire’s Turbo or simply learn about it, we’re a match!

RailsConf 2023

00:00:21.480 here I want to take you on a journey to a place that some of you may know a
00:00:29.039 country is so magical a country that is called alagasia
00:00:34.620 and in this country a villain rules spreading fear across the subjects
00:00:39.780 a dark King a dragon rider who's named gabatorex in this Dragon Shri Khan
00:00:46.440 but then luckily another Dragon hatched and chose her Rider The Majestic Dragon Saphira and her
00:00:53.219 Rider Aragon that the resistances spark of hope again Our Hope
00:01:00.360 and now as the two armies face each other our hero Aragon steps forward with
00:01:06.479 a desire to save all the man on both sides he demands gabatarics to a duel where
00:01:13.260 The Winner Takes Over command of the other side and we all know that dark Kings have
00:01:18.979 incredibly big egos so he could not reject but he accepted
00:01:24.720 the challenge there's one issue though galbatorex is not even on the field
00:01:31.259 he barricaded himself in his castle and this is across the country and not even the Dragon Riders magic can
00:01:38.340 travel this far but then we step forward as we are one
00:01:44.220 of the few knowledgeables of a magic that is even Beyond The Magic of the Dragon Riders
00:01:49.920 a magic so old and Powerful that most believe it is forgotten
00:01:55.799 imagine that goes by many names which people only can whisper rubion rails
00:02:02.780 action cable two of the streams and we all know this magic is so old
00:02:09.179 that no one tries to learn it anymore and we also all know that it's just intro
00:02:16.860 so we take on this enormous responsibility and help Aragon zafira to fight
00:02:23.340 gabatorex in an epic battle of tick attack toe
00:02:30.239 so welcome everyone to my talk exploring the power of tube streams and action cable
00:02:36.000 but first Who Am I who is this Storyteller across the campfire the one
00:02:41.099 that got all your attention which probably is because the campfire stage and so you kind of must watch me
00:02:47.819 um so my name is Kevin lipos I'm a business administration business
00:02:53.040 administration Bachelor turned rubyist by visiting a boot camp so thank you
00:02:59.220 um and I'm from Germany so now I work at a software engineer at
00:03:04.379 portagon which is a fintech in Frankfurt Germany and I've been there since roughly three years now
00:03:10.739 so what we do there is we provide simple reliable and independent access to the
00:03:16.260 private Capital Market and yes we got a beautiful rails monolith for that
00:03:23.159 also I'm one of the co-organizers of the Ruby Meetup in Frankfurt
00:03:28.680 and this is also my very first conference talk ever so please bear with me I'm quite nervous
00:03:40.200 thanks so before we dive back into our story I just want to ask you one question just raise your hand does
00:03:46.920 anyone here even know the inheritance cycle by Christopher paulinho which I based My Story upon
00:03:53.519 all right more than I expected amazing so um for you it makes probably a little
00:03:58.799 bit more sense for the others I still hope it's going to be fun so if you like fantasy and haven't read
00:04:06.720 those books I definitely recommend it so just to tell you why I am telling the
00:04:11.760 story it's because I'm currently rereading those books as I never finish them in my teenage years
00:04:17.760 and I don't know how's that with you but when I read something I connect everything with it so they let me have
00:04:24.240 no choice but to use the story and the talk so let's go back in
00:04:29.580 to cast our spell we need to be exploring the power of two streams and action cable which cocidentally is the
00:04:36.000 name of this talk and by that I want to prevent you from something that happens to those who are
00:04:42.419 unknowing what also happened to me when we did a project at work where we needed some customization for tuber streams and
00:04:49.080 action cable um which is like we just couldn't find the advanced examples that we needed so
00:04:56.040 we Dove on to a long journey of trial and error and researching
00:05:01.800 so the goal for this talk is to provide you such an example and to spark your imagination for your
00:05:10.620 own spells for your own use cases of the old magic cotubo
00:05:16.500 and as anyone who is knowledgeable about magic knows we need to be careful in how
00:05:22.139 we conduct it right otherwise the results could be devastating so first
00:05:28.620 we're gonna explore the ingredients of our spell and explore theory behind it a
00:05:34.500 bit so we're going to dive into web sockets we're going to see how action
00:05:40.259 cable adds some spice to it and how it turbo streams in the end garnishes Our Spell
00:05:45.660 and by that just when you're one of the few candidates that want to be included
00:05:50.820 into the magical cycle of Turbo just don't have no fear we'll cover the basics so that everyone now can follow
00:05:57.660 along then we will be constructing our spells so
00:06:03.180 we're going to build the game of tic-tac-toe we're going to start with a basic game skeleton and from there we're
00:06:10.259 going to add three constraints to it each discovering another part of action cable and turbo streams
00:06:17.520 and last but not least we will let our magic work and we will cast our spell and by that we're going to watch the
00:06:24.240 epic game between Aragon zafira and galbotorix and going over everything we learned in the talk
00:06:31.560 so now let's start off with our three ingredients and explore the theory behind it a bit
00:06:38.039 and first here let's get everyone on board what websockets are so web sockets are about real time or at
00:06:47.160 least close to real time so for me it's always easy easiest to
00:06:52.620 understand that when I again remind myself how HTTP works I mean we all know that but still let's go over that a bit
00:07:00.000 so let's take a chat as an example um when we when we want to have the new
00:07:06.360 messages then we first need to request it from the server and then the server responds by sending
00:07:14.220 us those new messages back the thing is only when coincidentally
00:07:19.560 our Scout on the field on the lookout for our enemies sends the message before
00:07:24.960 our request to the server only then we can receive it
00:07:30.780 with web sockets that's a little bit different with websockets we have an open connection to the server all the
00:07:37.440 time and this means the server can send us anything anytime they want without us
00:07:42.840 needing to request it and by that as soon as the Scout sends
00:07:48.120 the message to the server they can directly forward it to us
00:07:53.340 and by that we still keep the advantage that we directly get the message and not just like maybe an hour later
00:08:00.660 all right let's go to our second ingredient which is action cable
00:08:06.720 so coding all the basics of web sockets might be quite repetitive and might
00:08:12.900 require some protocol level level knowledge so that perfectly fits into a framework
00:08:18.360 and of course rates covers Us here so action cable is the rails magic for
00:08:24.419 websockets but let's dive a little bit more into that by Consulting our amazing rails
00:08:31.139 guides so basically action cable integrates websockets seamlessly into every rails
00:08:39.479 application and by that it allows us to write real-time features in our beloved Ruby
00:08:45.000 language it offers us a gives us a full stack
00:08:50.339 offering and by that stays true to the idea of rails that one magician AKA one developer can do it all
00:08:58.080 for that it provides us a client-side JavaScript framework and a server-side ruby framework but let's keep it like
00:09:05.519 that for now more than when we construct Our Spell so let's go to our third and last
00:09:11.640 ingredient and explore the magical world of hotwire a little bit and talk about
00:09:16.980 two of the streams Broadcasting so we're smart magicians right so at
00:09:23.100 least we think we are so that's why we weave a little helper into our spell as
00:09:28.980 Tupa streams just allows us to use action cable way easier
00:09:34.320 so it kind of is an abstraction of action cable which by itself is an abstraction of websockets
00:09:42.420 but what this exactly does turbo stream broadcasting providers basically it's a simple concern that
00:09:49.260 comes with the tuber rates jam and which is now by default included in the in raid 7.
00:09:54.959 so it gives us Little Helper spells so methods that then do the magic in the
00:10:01.440 back we can use them as the gem also adds that as an initializer
00:10:08.399 the two active record so we can trigger the broadcasting right from there so we
00:10:14.760 sent websocket messages then right from the model so
00:10:20.700 all in all tube stream broadcasting provides us a plug-and-play solution so just install the gem at around three
00:10:27.540 lines of code and that's it it just works by that it's really easy to use even for
00:10:33.480 our smallest magicians but the cool thing is that's not even it it also gives us automatic Dom updates
00:10:42.720 and that's important because normally without trouble you would receive the
00:10:48.060 websocket messages and you need some client-side JavaScript to do something with it right
00:10:54.720 but with turbo it sends us HTML over the wire so in all know Hotwire and then the
00:11:02.459 gem automatically updates the Dome with it so that's nice
00:11:07.860 all right now we finished the list of ingredients already
00:11:14.339 take a short breath and then we receive a foggy picture in
00:11:20.279 our head gabatarix and Drake and started to become impatient so let's quickly move on with
00:11:26.700 constructing our spell and build the game of tic-tac-toe so first things first
00:11:33.660 let's get everyone on board what tic-tac-toe is I know most of you maybe know that some may may not so
00:11:41.220 tic-tac-toe is a game for two players where you start off with nine empty fields
00:11:46.440 then the players take turn and Mark those fields so first player one
00:11:51.779 then player two and as soon as one field is marked you cannot unmark it and you cannot take it
00:11:58.079 away from your opponent as soon as then one player reaches three in a row
00:12:03.720 the vertical horizontal or diagonal then this player wins so
00:12:10.620 basically that's the game that we want to build the big challenge that some of you might
00:12:16.800 already see are instant notifications that one player gets notified when the other player makes a move
00:12:23.040 but the cool thing is with our tool magic that will be no problem
00:12:28.860 so let's go on and build our skeleton game
00:12:34.140 so what do we need basically we need two models so the player and the game let's start with the
00:12:40.920 player a player belongs to a game it has a name and a character assigned like a
00:12:47.279 dragon or a sword and we're gonna assign that character in a callback
00:12:52.680 then let's look at the game which is even simpler as it just has many players and stores the values so the characters
00:12:59.600 of each of its nine fields and now before gabataric's entry can
00:13:05.160 become even more impatient let's make our game playable and at the first constraint
00:13:10.920 which should look a little bit like this so what you see here is we have two
00:13:16.019 clients where localhost and have the epic game for oligasia so first things first we need to add
00:13:22.800 players to it and of course the good ones Aragon zafira are their first
00:13:27.899 so here they are we see they got Schwartz assigned they still need to wait for the opponent
00:13:34.100 and it looks like they cannot actually start to play yet
00:13:39.300 so let's add our notorious latecomer galbotorix the bad King to it
00:13:47.639 so here he is we see that he plays Aragon zafira he
00:13:52.980 got the dragon assigned and it looks like both parties can now start playing
00:13:58.019 so let's do that
00:14:03.240 so first Aragon and zafira make a move then gabatorex does
00:14:10.260 so that looks like it's working let's just sum it up what we just saw
00:14:15.959 so we saw that there are two clients involved otherwise you cannot display
00:14:22.380 and we saw that as soon as Erica and zafira made a move and galbatore is directly saw the effect
00:14:29.160 of that action which comes with some UI differences
00:14:34.740 um but that's not only the move but also like the name of the player is different and the name of the opponent
00:14:41.880 so we come to our first constraint which is actually like two things first that we
00:14:47.339 need two players to start the game the second is that one player directly needs to see the move of the other player
00:14:54.240 so let's do that and start with the two players so on the left side you see that
00:15:00.300 when there's only one player they cannot start on the right side you see as soon as the second player joins
00:15:06.779 the board changes and both can start playing for that we need to connect the Stream
00:15:14.399 so we need to connect the client to the websocket so they can receive any kind
00:15:19.560 of notification and then we need to notify the opponent about that so first things first let's just imagine
00:15:27.899 that everything happens on the games show page here we just add a one liner to it and
00:15:35.579 that's it we're connected to the websocket or stream which I try to call it from now on
00:15:41.579 um let's look at this in Parts though so first we have the tube stream from helper which is provided by the gem and
00:15:48.899 this connects us to a stream to which stream then is defined by the
00:15:54.060 next part as this is kind of the stream name so we could here also use just board and
00:16:01.320 get rid of at player which would be technically perfectly fine though the add player makes it kind of
00:16:08.459 like private is we can later Define the exact single client to which we want to
00:16:14.699 broadcast to and that's because when we broadcast something we always broadcast it to all
00:16:21.120 the clients that are connected to the stream with the same name and the add player makes that kind of unique or at
00:16:27.660 least dynamic so we're connected and you can verify
00:16:32.880 that by looking at our Network tab so here we see that indeed we're
00:16:38.339 connected we're subscribed to a channel where we're welcomed and we receive those amazing things and those pings are
00:16:46.019 kind of important as they're like the heartbeat that the connection is and stays open
00:16:55.259 it's all right we're connected now let's notify our opponent when someone joins and this we do a after create callback
00:17:02.759 in the player model so let's see how that looks like
00:17:08.339 so first we need the broadcast update 2 method that also comes with the gem
00:17:13.559 and then with the and then we Define the name of the stream to which we want to
00:17:19.799 broadcast so the opponent's board um stream and when we look at the front
00:17:25.079 end that quite mirrors what we have there so that's good
00:17:31.620 next we need a Target a Target is the ID of the Dom element that we are going to update and by
00:17:38.760 update here I mean that we're gonna replace the inner HTML of that element
00:17:44.340 and of course there are also other math methods that come with the gem like
00:17:49.500 replacing or stuff but here we Define the update too and just so you see again what it is
00:17:57.179 what we want to update it's basically that in the front end so next we need to Define what we want
00:18:04.080 to update that with which is the gamesport partial
00:18:09.120 and I don't know how you feel but for me this kind of looks somehow similar to a
00:18:14.400 simple render method in the controller so I think that's not too hard to understand
00:18:19.799 but still to make it complete we can also of course pass locals to the
00:18:25.080 partial let's pause a second take a breath and
00:18:30.720 think about what we just did so we just connected a client to the websocket we send a message through that
00:18:39.539 connection to the client and then we are also updated the Dome with it
00:18:45.120 and that with almost no code it's not freaking amazing
00:18:55.860 well all right we now updated the board but it would also be nice to know
00:19:02.039 um against who we are actually playing right so let's also do that quickly
00:19:07.679 and simply add another broadcast update to to the method that we already have there
00:19:13.620 um so this time only we've gone to Target so we're going to update the opponent name Dom element with the games
00:19:20.400 opponent named partial and that's it so you can send two broadcasts from the same method in this
00:19:27.419 case and updating two different things of the Dom with it so all right
00:19:32.700 we have two players connected now and now next thing is we don't want that
00:19:38.520 arrogant zafira like play blindly we need them to know what gabatorics does
00:19:44.100 so we need to send them the action
00:19:49.679 thing is we're already connected to our stream we are the tube stream from helper so we don't need to do that
00:19:56.160 anymore however let's now Define what happens when someone actually makes a move
00:20:03.059 and for that let's look at one single field of our board
00:20:08.760 basically that's just an if else statement so when the field already has a character
00:20:15.120 assigned we simply display the character if not though we have a formula there
00:20:20.160 which is also like a really simple and short form as it just has some hidden attributes values that we then will need
00:20:27.179 later in the controller we're just going to add one new magic to
00:20:33.299 it to the stream so we're going to wrap this form into a turbo to a frame sorry
00:20:39.299 and by that make use of another part of the turbo magic which goes kind of like
00:20:45.900 this so by default a navigation that happens inside a frame it's just scoped to that
00:20:52.620 very frame and when the response of the navigation like here the form submit contains a
00:21:01.380 frame that has the same ID then the new frame simply replaces the old one
00:21:08.580 so we're going to knit that in a second so we submit the form and then we're
00:21:13.799 going to reach the game controller against controller update method and here we just update the correct field on
00:21:20.220 the game quite easy for now and then the game of course updates
00:21:27.120 so first thing is now we want to change our own UI and we do that by simply
00:21:33.059 rendering that's the right one I have assembly
00:21:38.159 rendering this something back to where the click so the form submit originated from
00:21:44.159 and we simply render a field partial back this is the same partial that we already have there this time only it
00:21:51.720 already has a character assigned so we're going to display that one and as this again is wrapped inside the
00:21:58.919 turbo frame that has the same ID as the field that's already there the new field with the character
00:22:06.320 replaces the old field in the front end with the form and that is the magic of
00:22:11.940 tour frames alright then so we updated our own UI
00:22:18.360 but we also need to update our opponent's UI so we do that
00:22:25.140 here in our K model so we're gonna add an after update callback here and this
00:22:32.100 just triggers another broadcasting so here we broadcast a replays to the opponent's board stream and by replace
00:22:39.840 this time I mean we're going to replace the entire Dom element that has the same
00:22:45.299 ID as the field and not only the inner HTML of it
00:22:51.860 and we're going to replace it with the games opponent tick partial which is the
00:22:58.260 same as as a field in the end it just adds a little visual stimulus so the short red background so that the
00:23:04.559 opponent sees that something just happened and that's it we updated our opponent's
00:23:10.620 UI so just to sum it up again with the
00:23:15.900 broadcasting we replace the field of our opponent and with a simple render method
00:23:22.740 with the help of tuber frame we replaced our own UI and change that
00:23:28.140 so our basic game already works now
00:23:37.260 but we're smart magicians right so we think ahead
00:23:42.299 and come to the conclusion that we cannot trust gabatorics to play fair at all
00:23:48.000 and our first thought is that he might try to add a henchmen to the game who manipulates the game in his favor and we
00:23:54.900 cannot let that happen so therefore our second constraint
00:24:00.600 is that we restrict the game to only two players which should look like this
00:24:07.860 so you see that we have three clients Aragon zafira are already there
00:24:15.179 and now we need to wait forget the Torx to join the game
00:24:22.559 so here he is and then next we try to add a henchman to the game
00:24:28.080 of course whose name is henchman because dark bad kings don't care about people's actual
00:24:34.679 names right so sad here we are and now it looks like the
00:24:41.940 henchman is in the game let's try to play though
00:24:49.980 so what we can see here is that the third client the henchman actually doesn't get any updates
00:24:57.539 um and for that to happen we need to reject the connection request of the
00:25:02.580 third client and for that let's start with our customization and talk about action cable connection
00:25:09.900 so action cable connection is kind of like the bottleneck of a websocket connection so
00:25:16.799 there's one connection instance per websocket or per stream and the action cable server can handle multiple
00:25:23.340 instances of course with different clients but a client can only have one
00:25:29.340 connection so just think of that like maybe a tunnel that is the connection between
00:25:35.220 the client and the server and the server when they want to send something to the client they always need
00:25:42.120 to send it through this tunnel and this is the thing that we can like destroy or
00:25:48.600 disconnect for a potential third client but first we need to pass something from
00:25:56.340 the client through the connection to the server something that helps us to
00:26:01.679 identify who is it that tries to connect the good thing again is the old roots of
00:26:08.340 our magic help us here is it passes cookies from the client through the connection
00:26:14.340 to the server so we simply add the player ID to the cookies
00:26:19.980 and that's it and of course probably we should be more sophisticated here and use an encrypted
00:26:25.919 cookie like a session cookie which just works as well but just for the sake of Simplicity we don't want to decrypt
00:26:33.360 something then later so let's do that for now and then as soon as we reach our action
00:26:39.900 cable connections so the application cable we can use this cookie to find the
00:26:45.059 player and can then decide if we want to allow the player or not
00:26:50.820 in which case we're going to reject the connection so let's again look at our Network tab
00:26:58.200 first a reminder so that's a successful connection we see we're connected
00:27:03.299 subscribe to a channel we're welcomed and we receive our pinks
00:27:08.400 when it's not so successful though we directly see that we get disconnected as unauthorized without any reconnection
00:27:15.900 attempt so we're not welcomed and we do not receive our beautiful pinks
00:27:22.980 so that's a win we just successfully hindered gabatorics to add the henchmen
00:27:28.980 to the game and help him manipulate it so that's cool but still we deeply believe that
00:27:35.700 galbotorix is decideful and we can very well imagine a scenario where it just
00:27:41.520 leaves the game and lands a surprise attack on the resistance but this ain't happening with us I say
00:27:48.059 so therefore our third constraint is that as soon as one player leaves we
00:27:53.640 need to end the game and notify the opponent about that so this should look like that
00:28:02.460 so again Aragon zafira are there already so let's now add cabatorics to it
00:28:10.260 here we are and we start playing
00:28:16.260 and now galvatore's just leaves the game and what we can see is that Aragon and Saphira get notified about that and the
00:28:22.860 game ended right but there's also another way of leaving the game
00:28:28.620 let's see how that works
00:28:41.760 so we stop playing again this time we just close the tab
00:28:47.279 and we also see that ericon and zafira got notified about that so cool how we
00:28:52.860 gonna do this now um we're going to talk about action cable channel for that so just imagining
00:29:00.240 the channel is like a chat room or room and when you're inside your room you can
00:29:05.279 hear everything so you could potentially receive all the messages that are sent into that room
00:29:12.840 so even though a client has still a single connection to the server a client could be subscribed to multiple channels
00:29:20.399 so that's one thing another cool thing about channels is we can Define behavior for what happens when a client
00:29:27.539 subscribes to it or unsubscribes from it and that's the thing that we're gonna need
00:29:33.179 so rails has an application cable channel a default one
00:29:38.399 turbo also has a default Channel which is the tuba streams Channel and that's the one that we connect to without
00:29:45.120 further ado and the difference is that it kind of
00:29:50.159 has some turbo magic added to it and it also has a subscribed callback
00:29:55.679 which is triggered when of course the client subscribes um in this callback we can
00:30:03.059 check if someone tampered with the stream so with the stream name especially in which case we can reject
00:30:09.600 it but for the sake of learning we'll not do that we want our very own game channel
00:30:17.340 just so that it's going to be easier in the future to add more channels to our Magic
00:30:23.279 and that for now looks just like the default turbo streams Channel
00:30:30.419 all right let's now Define the flow for what happens when a client connects and
00:30:35.940 subscribes so first a client connects to the action cable
00:30:41.220 connection instance where we can reject the henchmen or allow the player
00:30:46.520 then they subscribe to the game channel which triggers the subscribed callback
00:30:52.740 and then one day they decide to leave which means they unsubscribe from our
00:30:59.700 Channel and that triggers an unsubscribed callback from where we want to trigger the
00:31:06.659 broadcasting to notify the opponent so that the opponents UI updates
00:31:14.520 so let's now just keep like that with all the pictures and let's go through it step by step in our magical Ruby
00:31:22.200 language so first we need to adapt the view a little bit as we now don't want to
00:31:28.919 connect to the default Channel but want to subscribe to our own game channel so we just add a simple hash argument
00:31:35.760 here next we need to adapt our connection a
00:31:41.580 little bit because we also want to access the player from our channel so we need to pass it through
00:31:48.260 and that works with a identifier so an identifier is like the identifier
00:31:55.380 for the connection you can have multiple ones if you like we only need one and all identifiers are passed through to
00:32:02.399 the channel then and to assign a value to that identifier we just change player equals to self
00:32:09.539 play equals and now we can access it from the channel so here we are and now we need an
00:32:16.440 unsubscribe callback which looks like that I know it was incredibly hard
00:32:21.899 so but they're already the highest rank of our magical cycle and can do this so well in the end
00:32:30.000 it's just really simple and we're going to broadcast again from the model
00:32:35.640 maybe some of you don't like that because it's like some view things within the model you can also if you
00:32:41.700 like broadcast right from here just need to add a little bit more code or from a service or something like that but the
00:32:49.140 basic idea of tuber is to do it from the model so we're doing that as well now
00:32:54.899 and here it is the last thing that we need to do is we broadcast our update to
00:33:00.659 the opponent's board stream we want to update again the board
00:33:05.820 element of the Dom and but this time only we don't even need a partial we just need a single HTML string
00:33:14.399 so that's cool and to already feel exhausted now like
00:33:19.740 we checked our three ingredients and carefully constructed Our Spell
00:33:25.500 so Now's the Time to let our magic work and cast Our Spell so let's do that
00:33:37.799 and our game begins to make it all work we delve into our three ingredients we saw what websockets
00:33:44.580 are we added some abstraction to it with rails action cable and even added some
00:33:51.059 more abstraction to it with trouble stream just to get some real-time Dom updates
00:33:58.260 and now let's start so Aragon and Saphira ask the good ones they're always first there and they join
00:34:05.519 the game waiting for gabatorex the notorious bad guy latecomer
00:34:17.099 so here he is we can style finally start to play and
00:34:24.599 to make that work we added some basic broadcasting abilities to our tic-tac-toe skeleton
00:34:31.440 and we added a turbo stream from Tech caliber to the front end to connect to the websocket and added some callbacks
00:34:37.679 to notify the opponent as soon as the other player joins as well as of their actions
00:34:43.619 so let's go on playing
00:34:49.260 but now watch out gabatory tries to add a henchment to the game this time a bad one
00:34:55.020 and here they go this though doesn't really work as we
00:35:00.060 adapted our action cable connection to reject the connector request of the
00:35:05.099 henchmen and then in the end
00:35:12.420 the need to finish the game as we adapted our own action cable game
00:35:18.599 channel um to broadcast as soon as someone tries to
00:35:25.320 leave and now let's see how that decides the faith of oligasia
00:35:34.400 it's a victory all his subjects refuse to obey him anymore and we can finally install democracy in alagasia
00:35:46.740 so before finishing up I'd like to thank everyone who helped me putting my talk and see if P together because they were
00:35:53.220 like kind of a lot of people so I were colleagues mentors coaches and I also like to thank again my
00:36:00.480 employer portagon as they kind of sent me here from Germany so they made it possible for me to come here and also
00:36:08.099 a big big thank you to the organizers here I have no idea if someone is in the room but thanks for putting such an
00:36:15.000 amazing first railscon experience for me together and giving me the opportunity
00:36:20.579 to speak and I know there's still one and a half days ahead and as I now can
00:36:26.520 really enjoy them even better so thanks for that if you want to connect
00:36:32.760 with me I have various social media here and also if you want to check that out down there is the link to the Repository
00:36:40.440 if you saw the little buck with the opponent's name there's where you can
00:36:45.660 open a PR and fix that so if you want to talk to me just talk to me in the hallway try me for lunch or
00:36:52.320 if you stay here longer are probably gonna do a road trip to New Orleans on Sunday so feel free to join as well
00:36:58.560 so um finally thanks to all of you for taking the time deciding to listen to me
00:37:05.400 for I think 40 minutes straight the end