How to use Devise with Hotwire & Turbo.js

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey guys this episode we're going to be talking about how to use device with the brand new turbo js from hot wire it's actually really simple to do this but hotwire has a few things that you might not expect so for example turbolynx previously just handled links and made ajax requests for those but now it will also take over all of your forums in the new version called turbo and that is a little bit problematic because of the way that it needs to support mobile so when you submit a form you are your browser actually keep track of that and see if it got an error and it will show a modal if you try and resubmit and so hotwire actually is set up so that will give you an error if you didn't redirect to another location when you submit a form but that's not very good because it makes it hard for us to render out errors so there's actually a bug fix in master that will handle 400 and 500 responses and replace the html on your page automatically if it's included in those responses so we can take advantage of that feature to make device work with turbo so let's dive into our application now the main thing we need to do at the moment is to use the latest version of turbo from github so we can include that new feature to handle the 400 and 500 responses so go ahead in your package.json go and replace your hotwired turbo reference to the one on github the latest build and that will include that fix now i'm using the free version of jumpstart here so we've already got a little bit of javascript for setting up rails ugs and i've removed the turbo links and replaced it with hot wire turbo and i've changed our event listener here to listen to turbo load and we can add a simple console.log turbo in there and we can refresh our page and we'll see that it will log out that turbo message and if we click sign up we'll get that javascript error from turbo saying you didn't redirect anywhere so the way we can fix this is we can go into our device initializer and we can add a couple of things the first thing we need to do is set up a parent controller i'm going to call mine turbo controller and we'll just simply define it here because we're not going to use it anywhere else and it will be a okay to do that here so our turbo controller is going to inherit from application controller as normal and we want to set up a responder and that is what devise uses behind the scenes to actually do the redirects and the renders and it basically is abstracting out your regular scaffold responses so when there's an error on create it renders new when there's an error on update it renders edit but those return 200 okay responses which is not something that turbo's going to like so we want to actually render a 422 error on those so that turbo can see that grab the html and then render that error on our page so what we'll do is we'll define a new responder class that will handle the new format that turbo uses so we'll call this responder and this will inherit from action controller responder and inside of here we can handle our different format so we'll say to turbo stream and define our code in there for handling that and then we'll say respond to turbo stream and html in our controller so that will tell the responder which formats we want to respond with then our two turbo stream so inside of our two turbostream handler we are going to implement a couple different things the first is that we want to say controller.render and we want to pass in options but merge in a formats key with the html value that's going to basically tell the responder to say hey let's render with the html format we don't want to look for a turbostream.erb file here and then we also need to handle the case where there is no template being found and that is going to be where we rescue from action view missing template error and we will say if it's a get request let's just re-raise that error but if it um is a request that has errors this is all stuff that is inside of the responders gem so if you want to understand what's going on take a look at the source code for the responder class that's where all this stuff is defined but it's mainly for html and javascript and json responses so we're adding this turbo stream format in to kind of say hey pretty much treat this like a regular html request um and so we have the default action to check for as well so basically if you submit a new user with mismatched passwords the validations will fail and the respond with resource will actually call this and say hey uh there is no response template for create.turbostream or create.html.erb and it will say but your object that you gave us has errors and there is a default action for create we know we need to render the new action and so that's where we handle this and so we say render rendering options and we merge in the formats of html so we'll render new.html.erb which is the template already built in to devise and we will change the status here to unprocessed entity which is a 422 error so that's going to give the error and the html back to turbo in the browser and it's going to replace the page with that stuff using the new version of the turbo js and then otherwise if it's some other use case we're going to redirect to the navigation location and all of these things are inside of the responders gem so take a look at that if you want to understand what's happening here it can be a little bit meta programming ish because it's so generic it can feel a little bit hard to understand now there's one other change we need to make this work for the registration and that is we need to go down to the navigational formats and add the turbo stream format here and that basically tells the responders gem that we want to redirect on turbostream and html requests so those formats want to redirect but if you're doing a json create we actually want to just render out the user as json so this is important so that we get the actual success redirect when you create your user so make sure that you have that otherwise you will get a strange error so let's go restart our rails server and boot up our app and try to create our user account so let's go to sign up we'll say chris chris at gorails.com our password let's put mismatching passwords we should get the error we can type in a valid password though and we'll be redirected to the home page and signed in so then we can go to our account and we can say let's update our password if we do this with a invalid current password we should see errors here and we do and if we change the password with something valid it should succeed and redirect us to the home page so all of this seems to work perfectly except if we try to log in and we give it an invalid email or password it just hangs and we can see this in our network request we'll make a post to sign in and our headers get a 200 okay and that needs to be something different so the way that we can solve that is that devise uses a tool called wharton underneath and warden is like a rack middleware that will handle the actual authentication for us and devise just does all of the railsy things around it so the solution here is to actually uncomment this and add a manager.failureapp equals and we're going to call ours the turbo failure app and we'll define that up here at the top class turbo failure app and this needs to inherit from the device failure app class so we can just override the devise defaults here and basically we want to add an override to the respond method and if the request format is a turbo stream format we want to redirect so basically on failure we'll redirect back to the sign up or sign in page with the alert at the top and otherwise we'll just call super and leave it to do what it was by default so that will handle everything as we need it and this is just another case where we're basically telling it hey treat your turbo streams like you would treat an html request that's really all that we've done here is just configured devise and the responder's gem to treat the turbo stream as if it was an html request and then add that status in so that our javascript knows what to do with the error response so now let's restart our rails server so that we have all that new code and we can refresh our page here and try to log in we'll say chrisagorails.com and some invalid password will log in and we'll be redirected back here and that will work so that is going to give us what we need there and we can type in a valid email and password to log in and we will be taken to the home page after being signed in so all of that works correctly there so the very last thing that we need to do to make this work completely is we need to fix this redirect because it actually adds a dot turbo stream as the format in the url which we don't need because these need to be treated more like an html request so the fix for that is actually a simple method inside of the failure app called skip format and it's simply a array of html we add turbo stream into there and the asterisk asterisk and check to see if the request format to string is included in there and that will do the trick so now we can restart our rails app we can go back to the regular sign in page click log in and we get redirected to the correct url without the turbo stream format being added so that's it we have a complete working device install we haven't had to change anything in the device controllers we haven't had to change any templates all of it's in our device config and that works pretty well now i expect that we should be able to add some of these things into device and the responders gem as prs so that this can work out of the box in the future but for now this will do the trick and make it quite an easy upgrade to add hot wire to your rails apps so that is it for this episode we'll be talking a lot more about hot wire turbo and strata and stimulus in the future i'm really excited about all this stuff and i will talk to you guys then peace
Info
Channel: GoRails
Views: 6,239
Rating: undefined out of 5
Keywords: Ruby, Ruby on Rails, Rails, Javascript, HTML, CSS, Servers, Databases, Screencast, Tutorial, Rails 6, Action Text, Active Support, Action Mailbox, Webpacker, Active Storage, Active Record, rails testing, ruby on rails testing, ruby testing, devise, rails devise
Id: yZDTBItc3ZM
Channel Id: undefined
Length: 11min 53sec (713 seconds)
Published: Fri Jan 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.