CRUD basics with current_user

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up friend thanks for joining us again we are in the series where we're building out a blog and we've built out authentication in this episode we're going to talk about how we associate posts with a current user assuming that we have some authentication mechanism in place whether we've built it ourselves which again i don't recommend i highly recommend using some tool to help you with authentication that has been really battle tested and is bulletproof um i would record i i personally use devise a lot of times you might also use a third-party provider like auth0 or something like that in this episode we're going to do is talk about how we can use that current user to scope or limit access or sort of do some authorization just basic authorization for creating posts listing posts based on that current user all right so here we are in the posts controller in the very first episode we scaffold this with rails g scaffold and talked about all the different pieces so if you're curious about that you can head back and check out that post or that that episode in this episode what we're going to do is use this uh we're going to use this method current user in order to limit access to the posts that are being returned in this this standard view to only those posts created by and related to the current user so the very first thing we need to do is make sure that we have a current user logged in before we even see this page we should not even be able to go to slash posts unless we have a current user so this is where we talk about before filters so we're going to say or before actions right so in the posts controller we want to ensure that there is a current user so we're going to say before action ensure current user you might also see this called like require current user or require logged in user there's a bunch of different ways that you might you might call this so let's call it ensure current user and we're going to write this as a method on the application controller so that we can reuse this sort of filter in other in other controllers in the future so we're going to say def ensure current user and the way this method works is we're going to see if there's a current user and if there's not we're going to redirect so if uh current user.nil then we want to redirect to uh like just the root route right so uh root path or whatever so if the current user or if this when we call this current user method if the value we get back is nil we're going to redirect to the root path and when we're defining a before action if there's a redirect that's called inside of a before action then the ad the other actions don't actually execute so we're not going to run index we're not going to run show we're not going to run new or anything if there's no user so let's head back over to our controller refresh the page undefined local variable or method root path so this should just let's just go to the like root i don't know uh slash i don't know what it's actually called refresh all right so we're sent back to the root path if we try to go to like slash posts again we're kicked out we try to go to like slash post slash three kicked out again so we need to be logged in in order to see any of those those routes that are for the posts controller so let's go to sign in and we're going to enter our email and password and recall in the last episode we built out authentication from scratch so now we have a current user that is logged in and we're able to see slash posts we can see posts one or you know we can edit it we can go back we can destroy these posts or whatever we can create new posts test test and create the post and then we can go to like slash posts again we can see all these posts this is fantastic right now what we want to do is we want to update the post model so that posts can be associated with a user so right now as we have it the only thing that a post has is a title description and then some other fields for id create updated that and we want to add a new column in there so that posts can be associated with a current user so let's go write a migration rails g migration add user to posts user colon references using references that should create a association for us so we're saying add reference to the posts table that's going to point out a user cannot be null and it is a foreign key foreign key means that at the database level we are going to enforce referential integrity meaning that like you can't have a post a row in the posts table that does not have a an id that points at a valid user in the users table so we're like going to maintain some referential integrity there so that is going to be a foreign key out to the users table and you can also do things like if you delete a post or if you delete a user delete all of its posts or you know there's a there's ways to like cascading delete the related items anyways this should i think this should work let's say rails sales db migrate okay when we try to migrate this we get this giant error it's super scary pg no no no column user id contains null values that's because we already have posts in the database we've already got these these three posts they're in the database and they don't have user ids so when we try to add this new column that has to be like referred to by the users table and it doesn't have any of that it crashes and burns so what we're going to do is we're going to go into the rails console here and we're going to say post.destroy all and then we're going to try to run this again so there should be no more posts in the database okay so now we have successfully migrated and we needed to do that because um yeah because we had to remove all the posts that did not have valid references to users so now if we go refresh this it's going to be no posts left that's fine right so we can still create a new post but when we try to attempt to create it it's actually going to fail because now we're seeing non-null you know the user id has to be filled in so the way this works right now inside of the posts controller here we're creating the post and we're passing in post params but recall that post params only accepts the title and the description so we're trying to create a new instance of a post object with that title and description that was passed from the front end but nowhere to be seen is the user id so how do we get the current user associated with this brand new post well one way we could do it is we could say like permit user id right and then we could add like a hidden input or something that had the user id on the front end that's a bad idea because anyone could could change that id on the client and pass in whomever's user id they want so we don't want to accept the user id from the client because we don't trust clients we don't trust users users our users are shady there's there's some shady users out there they're going to try to do funky stuff so we don't want to trust that the user id is passed in from the client instead we want to use that authentication mechanism or that authorization mechanism that we built out as part of current user right because that's using those signed and encrypted session cookies that can't be really tampered with and you can't really change it to another user so instead of passing in the user id here what we're going to do is we want to pass in the user id when we create the post we could say we could also say like app post dot user id is equal to current user.id remember that like we have to have a current user to even view this page and here we can call this after we've initialized post because this doesn't actually persist it to the database the error we're seeing on this page is happening when we try to save the post you can see it's on that line so we could technically do it like this in two lines however there's another way that we can do this so let's actually let's actually uh go back here we'll refresh the page test with user test with user whatever click create post all right post was successfully created right and now if we look in the database post.last we see there is a post here it has id 7 title description i think i need to reload post.last okay so now we can see the user id is user id 4. so now if we say like user.find 4 that's going to give us back the user who's currently logged in that's wave at cjf dev right and so that current user is now associated with this post okay so what we could do is if we tried to say like u equals user.find4 and u.posts wouldn't that be nice if we could just say like u.posts and it gave us back all of the posts that were related to that user or if we could say like p equals post.last and then say p dot user and it would give us the user that was related to that post that would be like super convenient and it turns out there's a way to do this and it's through active record associations so we're going to go into the post model and whichever model has the foreign key so in this case this posts table is where the foreign key lives right user underscore id is the foreign key it's not the primary key it's the foreign key it's not the it's not the id it's the thing underscore id okay so this is the the model whose table contains the foreign key that's where i always start building my associations and that's where the belongs to is always going to be it always belongs here so we're going to say belongs to colon user by saying belongs to user application record has methods under the hood that knows how to associate this post and look up that user model so now if we were to come back over here and pull up that post post dot last and say p dot user now we get back the actual user for that post so we're seeing that user model come back so that's great now we can still we still don't get p dot user dot posts we don't get to see all of the posts for the user because we have to go to the user model and we have to add another type of association here called has many so here we can say has many posts and by doing has many it knows that it needs to go into its associations singulars class and find the foreign key that points back at this class based on its its name underscore id and it will now say select star from posts where user id equals self.id basically so whatever the id is of this user so that's pretty cool so we can say reload and now we can say like u equals user.last u dot posts and we see nothing what okay you oh cause user.last is seven so u equals user.find4 and then u.posts and now we see the post that we just created okay so that's cool um so now we can go either way so we can say like u dot u.posts.first.user and that should give us back the user etc etc so we've got these like circular associations or relationships between users and posts what's super cool is that now that we have this has many posts association we can do something called building through the association or yeah so we're going to build through that association so we're actually going to say current user.posts.new instead of using the class name there so instead of doing this instead of doing this we can now do this so this instead of doing the classname.new now we're saying currentuser.posts.new and by building through the class or by building through the association we still get back an instance of the same type but the id the user id is going to be set so let's actually do that over here so u is still a user so we can say u.posts.new and that's going to give us back a new post and the new post notice this the new posts user id is already set for us by default it doesn't have title description or whatever so it is what it is but when we pass in post params that's where it's going to get the title and description and when we save that's when it's going to get the id created updated at so this is how we create a post that is associated with a current user in one line super handy and now we have associations so all right so we come back over here uh we can we can see the show page for this post we can edit the post we can you know update it back whatever see the posts here now if we log out let's sign out or register and this is going to be a new author tony tony at example.com tony's going to be very prolific we're going to log in as tony all right we just created tony we're still logged in as us because actually let's fix that now so in the users controller when we log in let's also session user id is equal to at user.id all right so now when we sign in as tony at example.com we are signed in to tony at example.com and if we create a new post let's create a new post this is like iron man oh yeah tony stark tony stark all right so now we're going back to slash posts now we see the posts from both the uh wave at cgi dev and from tony okay we can actually update our posts thing so it showed the author but what i wanted to do was limit it so i can only see the posts that i created sort of like a diary right right now we can see the posts that anyone created so if we go back to our posts controller up here instead of saying post at all now we want to say current user.posts okay this is going to return that association that we had that we just created in the user model and now if we refresh the page we only see the posts that we created so if we go to the show page we see post 8 we can see the post we created and if we go back to posts we can see we can see only the posts we created if we go back to show though we notice that 8 is here in the path and if we're like a really clever user super smart and we're like oh gosh you know what if hours was the eighth post i wonder what was the seventh post so then they click they type in seven and they're able to see the post from the other user we don't want that to happen right and so what we can do is we can go back to the terminal or back to the back to our controller and instead of just setting setpost based on post.find again we're going to use that association so current user.post.find so now if we try to see post 7 if we refresh the page boom activerecord not found in production this would show a 404 page this is exactly what we want because this user is not allowed to see post 7 but they are allowed to see post 8. okay so now if we go back we can create another post you know this is uh i don't know pepper potts whatever okay so now we can see post 8 we can see post 9 and we can see all of the posts that tony created and if we were to log out which i guess we need a logout button let's go so in the application like uh html erb in this template if we're logged in let's also add a link link to i guess we're going to call it like log out log out and we will say method actually we'll just go log out and we'll say this is going to the um gosh what is the routes sign out it's going to go to the sign out path all right let's see if we can okay we got a link it's going to go to sign out that's an unknown action go to our sessions controller and down here at the bottom we need to add a method for destroy and this is going to say session user id is equal to nil okay because this is how we logged in this is how we're going to log out and then we want to redirect to the sign in path okay if we refresh the page we're redirected back to the sign in if we try to go to posts we're redirected back to the route and if we go to sign in and we sign in as wave and we're logged back in we can only see our post right if we show it we can see post 7 but we cannot see post 8 because that's not our post so we can come back over here to posts but there is another weird one right where we can see show post 7 we can't see post 8 but can we edit it uh no great because set post is is the thing that's setting it um all right so let's go back to post 7. we're going to get we got to get real fancy here so we're going to say edit and then we're going to inspect the form for this edit and we're going to try to edit another post that's not ours so we're going to edit we're going to try to edit post 8 and pass in something new like hack or hack or and we're going to say update post oh authenticity token invalid okay did we lose that we lost something in our invalid authenticity token did we mess with the authenticity token ah i wonder if the authenticity token got smarter and is like now matching the route too or something um i don't know let's say like changed update post oh it might be updating it i think it did update it and we redirected to post date so if we look in the in the in the server log here we received a patch to posts8 and we passed in our description which is changed and then we got a 404 okay great so it looks like it did not change it but let's just confirm reload post dot find eight okay great it still says iron man all right that was that was scary okay so let's go back to our posts controller let's see if there's anything else we need to update here this post this this post dot new is fine that's that's okay we don't care that that one doesn't have a current user because we're just creating a dummy post for the new route that's totally fine um we've got our create as updated up um right so everything else now is scoped to the current user for posts so now users are not allowed to mess with each other's posts and this is how you would set up like some really basic authorization and also how you would associate objects with a current user it's almost always your controller actions when you have some sort of authentication or dashboard or whatever are always almost always going to be building through that current user and that is like the current user method is a pattern that devise also uses so that should be useful uh hopefully that was a useful exercise thanks so much for watching and we'll see you in the next one you
Info
Channel: CJ Avilla
Views: 347
Rating: undefined out of 5
Keywords: cjav_dev, web development tutorials, web development for beginners, vim, ruby, rails, javascript
Id: 8hfQbkw4snc
Channel Id: undefined
Length: 19min 55sec (1195 seconds)
Published: Fri Aug 13 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.