Hotwire in Rails 6.1 - A First Look At CRUD With A Hands-On Todo List | 20in20 - Week 18

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Awesome, thanks!

👍︎︎ 3 👤︎︎ u/erlingur 📅︎︎ Dec 30 2020 🗫︎ replies
Captions
hello everyone and welcome back to another episode of the 20 and 20 challenge this is part 18. uh and today i actually have something a bit special a bit unplanned but i spent the last couple days working on trying to get familiar with hot wire rails so today we're going to be taking a look at how to use hot wire rails to create a to-do list similar to the to-do list we made in week 15 i believe so we're just making a very simple to-do application but today we're going to be creating it using hot wire rails and this is just a really simple way to leverage the power of action cable and turbo links and all that package it together and provide an alternative to a front-end rendering framework and instead have the a bulk of the work done on the back end and then just push those updates as html updates through to the front end so you're going to notice that while we're setting up something similar to view we already have this like web socket communicating thing where we have a redis database running in the background and we're doing pub subs to it so if we change something in one browser window the other one updates so all of that is kind of also happening here which of course means that this is going to be a great tool if you're interested in doing you know chat rooms or any sort of websocket communication you'll definitely want to check this out but i'll be curious to know what you guys think of hotwire so you know if you have any thoughts about it or questions about it leave them down below and maybe we can have a discussion about it but that's going to do it for me let's go ahead and let's jump into some code okay so this is the application we're going to be building today and it's just a very simple to-do list where you can you know create a to-do item so i'll just make an item that's like uh do video intro and i'll create the to do and you can see that when i create it in one window the other one is automatically updated because we're running a redis database which is used for pub sub which is the publish subscribe so when you publish to one the other one is subscribed to it it gets notified then it says okay i need to render this and then if you like complete it to do you can see it's updating on both screens and you can do like inline edits so i'll change this to like uh a deleted to do click update and then we can hit destroy and that gets rid of it or you can you know click update and then hit cancel and it won't do anything so this is what we're going to be setting up and this is all being done with hot wire so this is going to be a little bit easier than using action cable to set up a system like this and it's going to largely leverage action cable and stimulus and turbo and it kind of you know bundles all of that together to make something that is fairly easy to set up but allows you some pretty pretty neat functionality but i'm going to go ahead and set all this up and move over to the text editor okay so the first thing we're going to want to do is we're going to want to add in our hot wire so for this we can let me just bump up the font size in the terminal for this we can do a bundle add hot wire dash rails that will add the hot wire gem and i believe the stimulus gem you can see here stimulus reflex our stimulus rails and then hot wire rails get added the other one we want to do is we'll also want to do a rails hot wire colon install which will set up rails or set up hot wire for us and you can see here that it adds a couple inserts into the application.html it does the turbo tags for us enables redus in the gem file so if we come into the gem file redis should be enabled switches the development sets up the readers database does some of the stimulus stuff adds in some javascripts and include tags and all that other good stuff so at this point if we want to run our redis database because we we technically have two that we have to deal with you are probably going to have to add redus manually if you don't already have it you can do this by running the sudo apt install redis dash server command if you're on linux and on windows i'm assuming you probably just have to go find a redis installer and set it up but then you should be able to run redis dash server if you want to just run it in a terminal like this or if you want it running in the background you can do redus dash server space space daemonize space yes and that will just run it in the background so now it is still running it's just we can you know still use this terminal window okay so that takes care of the redis setup now let's go ahead and let's set up our app so we're going to do a basic scaffold for this similar to what we did in i think week 15. so we're going to do a rails g scaffold to do's and we'll give each to do a title and a completed boolean so we can go ahead and run that and then we can come into our db migrate and our migrations and we can just say let's make this default to i guess false is what i had it so we can do that now let's do a rails db colon migrate command to migrate our database and then we can do a rails s command to start our server so now if we refresh we'll go back to our default rails page and now we can go into config and the routes.rb and then we'll just say route to the to do's index path and then we'll refresh the page and hopefully get sent to our to do's index page which it looks like that's what happened the next thing i'd like to do is we can actually close this we're going to just quickly generate another controller so we'll say rails g controller and we'll just call this the completed controller we're just going to generate this because i don't feel like making this controller manually so this will make a controller file for us here it'll be called the completed controller and if we come into our views you'll see that we do have a completed view folder we don't actually need this but um you know you can delete it if you want to but let's go ahead and let's pop into um probably one of our views so let's go into views to do's and then let's go into our index.html.erb file so what i'm going to do here is i'm just going to get rid of all of this save it and i'll do a rails s to start the server because we shouldn't need to restart the server for this so this will wipe out our page i'll just do an h1 that says a this is our hot wire let me bump up the font size this is a hot wire to-do list h1 save that refresh again uh and then we have a couple tags that we can use here so the first one you want to know about when you're using hot wire is the ability to do a turbo underscore stream underscore from and this is just where you're streaming the information from so how this page like where this page is getting its information from so when you saw that hot reloading that was happening uh where was it getting that info from and we're gonna say it's getting it from to do's we can save that refresh nothing will happen we can then come down here and we can do another uh erb tag we can say ruby or turbo underscore frame underscore tag and this will be for our to do form do oops and then we can end this one and this is where we're going to render this underscore form.html.erb partial so we'll just do that real quick we'll say render form and then we need to pass to the local so for this we'll just pass in our at to do now this doesn't exist yet so when i save this and i refresh it's going to throw an error and that's because this at to do is something we haven't created in the controller yet so if we come into our to-do's controller real quick our index we can just say at to do equals to do dot new save that and then once that formats we can refresh and we now have the ability to create a to-do item from our index path so let's go back to our index page after we have the form we then want to say turbo underscore frame underscore tag for to do's do and then in here we just want to do a render for all of the at to do's now this is going to work if you have a to do partial but of course we don't have a to do partial so this is like what what do you want me to render here of course it has no idea but we can very quickly fix that so let's go ahead and let's make our to do partial so we'll create a new file say underscore to do dot html and then in here we can do another turbo frame tag for the dom id to do do and then we'll just say end and the way this works is you're streaming all this info from todos and you have these frame tags and these frame tags are basically pieces of uh html that it will hot reload so instead of doing an entire refresh of the page whenever something happens it's just going to reload whatever's inside of one of these frame tags so if i hover over this i grab the body and i expand this a bit you can see here this is our cable stream and you can see right here we have different frames that appear so this is our two deuce frame and this is our form frame i don't know if this is visible i might have to scroll in but basically whenever something changes it will grab this frame in the independent from the rest of the page so like let's say you do something to delete the form it'll just delete the form but it won't refresh the page it does that by just grabbing info from the redis database as opposed to the way it works in a normal like javascript front end application where you just have all that stuff running around in the client side okay but now so let's very quickly add um let's go to rails bytes so go to railsbytes.com and let's very quickly grab bootstrap so we can scroll down i think and then grab the bootstrap gem we'll copy this to the clipboard we'll stop our server and we'll just right click to paste it and hit enter this should add bootstrap into our application and we're just doing this because some of the styling i had there did rely on bootstrap and it always helps to do stuff like this in the tutorial just in case this breaks something so that you know i can make sure that when you try to actually use this in the wild it actually works but we'll run a rails s again come back here and we'll refresh and i'll just open up my console and see if it's upset about anything doesn't look like it so let's go ahead and let's try and create a to do's uh set up here so we're going to give each to do a card so let's say this has a class of card and oops not end slash div i'm in rails mode right now uh then we want to give the to do a div with the class equal to card dash body then we want to say this is a to do if it's completed so we'll do let me full screen this we're going to do a ternary inside of here which of course isn't the most readable thing but this is just very quickly to grab the class for our um to do item so let me do this so if if to do is set to completed then give it the completed class otherwise give it the not completed class and now we of course have to go actually set up this this completed class inside of our style sheet so we'll just remove that and then in here we can then close this div and then we can do a to do that title to render the title we'll just do a br and then we can do a div with the class equal to so div class equal to we had button dash group and then float dash right we'll close this div and inside of this we'll have three different links so we do a link to complete and this is for the update completed path which is for the controller we made now i don't think we actually made this completed path yet so just bear with me and then we give this an id of to do dot id and a to do of to do and then a class of i think button uh button dash was it button dash secondary i think is what i have so we can save that we can come into here refresh of course we don't have it to do yet so let's just create it to do that creates a to-do right here but of course nothing refreshes on the page now if we actually refresh we should get an error for the update completed path so let's go ahead and define that completed path real quick so for this let's come into our config and our routes.rb and then here we'll just do a let's do it above the root we'll do a get for slash completed slash colon id and we'll do this to the completed update action so it's the completed controller the update action and we want to do this as update underscore completed so we full screen this this is what the full uh route looks like we can move this back over and we can refresh so now we have uh our text is a little gray here that doesn't look great so now let's uh let's come up here and let's fix this button real quick so this is going to be inside of app assets style sheets because we generated this scaffold we are going to want to delete this scaffold.scss delete that refresh and now it looks a little bit better let's now very quickly style this to do and we can just do this by coming here and for the completed to do we just gave this a background color of oops rgb and it was 124 233 91 and then we have a dot not completed it is set to background color rgb one seven seven one seven seven one seven seven save that refresh and now we have uh a gray to do so that's great pun intended but now if we click on it it says the action update cannot be found for completed controller so we want to go set that up real fast that we can come into our completed controller and then here we just want to do a def update oops def update and and then we just need to say at to do equals params.fine sorry to do dot find by the params id at to do dot completed equals not at to do dot completed so we're just inverting that and then we just do it at to do dot save so now if we come back and we refresh we can hit create to do which we'll create an empty to do and then if we click completed on that it will say the completed controller update action is missing a template for request formats text html so why is it saying that well if we come back to our index page sorry not our index page if we come into our to do model uh we need to set up the ability to actually stream these things so the way we stream these well first thing we'll do is we'll make sure we can't make a empty uh empty to do like that so we'll say validates the title the presence of true and then we'll just go back to localhost port 3000 real quick and we'll refresh this so validates the title presence true we then also want to do a couple after commits so with hotwire you can say after create commit or you can say after update commit or after destroy commit commit but for this one we want to do after update commit we want to broadcast replace two to do's and this is the to do's we set up earlier that we're streaming from so when we say stream from to do's we're streaming from this thing that's broadcasting to the to do so after we click update it sends it to the readers database by broadcasting it to the to do's list which we are uh streaming from in here and that's how this finds out that it needs to then re-render this turbo frame tag with the at to-do's to update this to-do item but now if we come in here and we uh click this so you can see it's a little bit upset about not having the template still and as far as i can tell and this might be a bug or i might be wrong here but when you try and do requests like this you need to come into app javascript and then pax application.js and i think you need to comment out this import rails and import turbo links and get rid of the rails.start and the turbolinks.start because it's using turbo now not turbo links and i did find this on a github issue off of the turbo repository so i'm assuming that's what you need to do but now if we hit complete you can see down here it just says uh no content found which is what we're looking for right now because we don't have everything set up but i don't expect it to error out when i do something like that so as long as there's just no content being found here we should be fine and you can see here that it is processing this update as a turbo stream which is good so why isn't this updating well if we come back to our to do's we have this to do.html.erb we have this uh to do title which is fine it's showing off the to do but one thing that we so it looks like i actually ran into an issue with this gem being a different version than the one i used for the demo application so we're going to do a little bit of live debugging here so one thing i'm noticing is i i'm going to set up the stream for deletions real quick so let's full screen this and below this after update commit we're going to say after destroy commit and it's the same thing we're just going to broadcast replace to the to-do's and then up here we'll also do a after create commit just so that we already have this where we broadcast replace or sorry bro where we broadcast prepend to the to do's and then down here this isn't replaced this is remove there we go let's save all of that we'll refresh if we click completed now that's working i'm not entirely sure why this isn't working because i just i just tried this and it wasn't working and now it suddenly is so that's a little bit interesting but it seems like adding in these creates worked unless there was something else that was wrong maybe one of the to do's that was created wasn't created properly no it looks like that it almost looks like the after update isn't working so if we comment that out and uncomment this it looks like you need both the after create commit and the after update commit in order for this to work but after you have both of those it seems like it properly broadcasts them so let's go ahead and let's check and make sure this is actually working inside of a second browser window so if we click it looks like this is already broadcasting our updates so that's great uh but let's see how much further we can take this so we'll uncomment this we'll move it back to here and then inside of a second rails console we'll just say or inside of a second terminal we'll just say rail c and let's do at to do equals to do that last we'll say at to do dot title equals a temporary title at to do dot save which you can see right here updated it without needing to refresh and you can see here it's broadcasting to the to-do's or to the to-do's redis turbo stream so it does all of that handles all of that now let's do a at to do dot completed equals true at to do dot save that works and now let's try at to do dot delete and you can see here that one wasn't streamed to uh the application like we would expect it to even though we have this after destroy commit so what's up with that well you'll notice here that i used an interesting choice of words i said at to do dot delete if i refresh it was deleted but because we're only broadcasting after destroy what we need to do is say to do dot last which will grab this one with the t title dot destroy and that will actually destroy it now thankfully the controller already has a destroy call inside of it so here it's calling at to do dot destroy so we should be fine there as long as we add in a link for that so let's go do that we'll come into our views our to-do and we'll go into i guess our to-do.html.erb let's full screen this and let's give this a button to destroy to do which is our the item we want to destroy and we'll say method delete which is how we tell rails we want to delete this and then we'll do a class of uh button button danger and we'll save that let's come over here and refresh so now we have a destroy button and a complete button so we can mark this as completed we can add another one and then maybe we don't want this another one anymore so we click destroy and it just deletes it just like that if we refresh it's gone still so that's good but one thing you might have noticed there is when i hit enter or when i created the to do the form is not updating so the next thing we want to look at is how do we make the form update so that it clears itself when we click you know submit we can do that by coming into the form real quick and then after the model to do just say comma id is equal to the dom id of the to do we'll save that refresh test create a new one that's still not being deleted so why is that still being a problem well it turns out that inside of our to do's controller we have to do a little bit of cleanup so if we scroll up to the top here and i'll just full screen we'll just go through this whole controller real quick the index show new and edit are all fine but inside of our create what we want to do is instead of redirecting to the at to do we want to redirect to the to do's path and then we want to say the to-do was successfully created we then want to make sure that we are in the errors handling the turbo stream so if we have an error we want this to say format turbo underscore stream and then we want to say render the turbo stream which is turbo underscore stream dot replace let me bump up the font size one more just to make sure you guys can see that then the turbostream.replace needs to take in the at to do and it needs to say partial is the to do slash form and then outside of that when you need to say comma the locals are the to do which is the at to do this is just passing in a local variable that this can then use in the form which of course in the form you can see right here is your to-do model so that takes care of setting up the create action because that's really all we have to do for the create now for the update it's perfectly fine to leave this redirecting to the at to do and for the destroy it is fine to leave this as the to do's url so now if we come back here refresh we can then say test case make this a completed one and you can see it removes the text from the form now what happens if i try to create an empty to do well we get one error prohibited this to do from being saved title can't be blank so then we say this one isn't blank and then we hit create and that creates a non-blank to do without the error and gets rid of the error and now we can say you know complete this or uncomplete it and then delete it the last thing i'd like to do though is set up that little edit button so for this we need to come into our form or not our form we need to come into our to do we'll just full screen this again and then in our to do partial we want to add a a third link or a third button here which is actually a link so say link to edit this will take us to the edit to do path which takes in the to-do and this is a class of button i think i said this was button warning like that now we want to come into our edit.html page and here where we render this form instead what we want to do is we can say put this in another you guessed it turbo frame tag with a dom id of at to do we'll say do and then we can do the end block down here we don't need a show button for this and we don't need a back button for this we just want to render the form but then let's wrap this in a div so for this what we want to do is we actually want to wrap this in a div that is identical to this one so if we don't wrap it and we refresh we hit edit it just removes that item so we lose our to do styling and you can very easily do this by just replicating the css that you have inside of your to do so this whole section right here basically just gets copied in let me replace this it gets copied in and the interior contents inside of the card body instead of having the title in this button group just has the render form call so you press that now when you hit edit you'll run into an error here oops run into an error here and that's because we need to replace oops we need to replace this let me full screen this we need to replace this to do with an at to do so it's using the same variable and if we refresh we can then hit edit and this now allows us to edit the to do now of course one thing you can see here we can click update and that works but how do we change this to allow us to cancel out of that for that we can quite easily just put in the link so we'll say link to cancel and then this will just point back to the at to do so we'll refresh we'll hit edit we'll hit cancel and there won't be anything here for it to display and that of course is because we need to come into our show page and we need to give this another turbo stream or a turbo frame tag so this needs to be wrapped in its own frame tag because it needs to know what what it's supposed to put here after you hit cancel because we're just saying go grab the frame tag the turbo frame tag from the show page so we'll just quickly say turbo frame tag with the dom id of at to do of course and we'll say do and then in here all we want to do is just render the at to do so it's just another call to render the partial basically so now if we refresh we click edit we click cancel it goes right back we can click update we can even uncheck this in here we can destroy these we can try to create an empty one it will air out this one will be valid we'll create it as completed to begin with and now what we can do is go over to local host port 3000 over here and we can do these same tests so we'll just say one two three we'll make that one completed four maybe i come over here and i want to delete the ones that aren't completed and then i want to uncheck this one and create another one that says ha got you and create it like that and you can see that very quickly you have something that's broadcasting this through the redis database across the rails pipeline and it's all perfectly responsive now of course if you only have one application for someone let's say it's all restricted based on user accounts you're going to have a similar experience to what you would have with like view or react where it just seems like a reactive application uh and it's just you know sending this over the sockets in the same way that uh you would have with like action cable but it's just but it's just an experience for the single user that you're sort of mimicking in that way and this allows you to put the stress on your back end as opposed to your front end so if the clients have a slower computer they they don't have you have to worry about stressing out their experience you can handle the brunt of that so that's one of the perks of having hot wire but i think that's just about it for this short little to-do list i'm hoping that in the next video i can uh set up something a bit more advanced using hot wire but i just want to get out this basic tutorial because like i don't know what i'm doing with this so i'm learning as i make this and this is a good way for me to get up to speed and then hopefully have you guys come into the next one a bit more familiar with how things work uh but let's go ahead and let's cut out to the outro video okay so that's going to do it for this episode of the 20 and 20 challenge hopefully this was helpful i'm curious to know what you guys think of hotwire now that you've gone through a tutorial on it uh possibly you know this is the second or third one you've gone through but i'll be curious to know what you guys are thinking so you know let me know down in the comments below what you guys think and maybe we can talk about it but that's going to do it for me hopefully this video helped you if it did please remember to like it subscribe all the other nonsense the youtubers are constantly saying if it didn't help you remember to dislike it so no one else sees it because it's a new tool set uh and we just don't want to subject people to bad tutorials on it right now but that's going to do it for me thank you so much for watching and i will see you in the next video [Music] you
Info
Channel: Deanin
Views: 5,961
Rating: undefined out of 5
Keywords: deanin, hotwire, hotwire rails, rails 6.1, hotwire rails 6.1, rails 6.1 tutorials, new rails tutorials, Rails 6.1 Hotwire beginner, beginner hotwire tutorial, deanin rails, deanin tutorials, deanin tutorials new, gorails, todo list, vue alternative, react alternative, html, ruby on rails, ruby on rails 6.1, 20in20, redis, redis database, action cable, action cable rails, stimulus reflex, stimulus reflex rails, stimulus action cable, rails chat room, rails sockets, socket rails
Id: NtTfYfWAzw0
Channel Id: undefined
Length: 33min 6sec (1986 seconds)
Published: Wed Dec 30 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.