BUILD A REDDIT CLONE [PART 3] RUBY ON RAILS TUTORIAL

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to part three of our reddit clone and today we will be finishing the build of our reddit clone and before we get into it I want to give a shout out to scout APM for sponsoring this video now you can check out their link in the description below and get a 14-day free trial so scout APM makes it easy for you to track performance issues in your code and eliminate n plus 1 queries and many other issues that we encounter when we build rails apps so getting into our application now I want to take things a little bit further so we've created this uploads and downloads in our posts table so this is an integer value it defaults to zero but we want to be able to increase this and decreases based on users action so let's begin by creating a new migration and this migration will be used to create a votes table in our database so in here we want to capture the account ID so that would be a reference to the account ID and we'll also capture the post ID and we'll also capture a billion values as a true or false value and this will be for the upload so if the value is true then it's not vote and if it's false then it is a down vote and then finally we will capture the time stamps to record when that vote was made so we will create a new file or our vote model so a vote will belong to an account and will also belong to a post and we will validate the uniqueness of the combination between the account and post so each account can only make one vote on a particular post so that would be based on the account ID and the post ID and we will create a callback or after the vote has been created it will increment vote and then we'll also do a after destroy that would be to reduce the number of votes so these methods will be called after the vote is created or after it is destroyed so the purpose of these methods will be to update total votes in our post so we have any value on the post to record the total votes they post up find and I'll use the ID of that post from the vote and it will increment the total votes on that post so just confirm this will double check our schema file and we can see here that we don't have the total value so let's just rename that and then finally we will call a dot save on that increment so E so in this case we're incrementing the up votes till number of our foods and we call a save method on that and we're doing the same thing when we down vote we want to reduce the number of votes and we will save that post also but one thing we need to remember here is that a vote can also be a down vote or a up vote so we need to decide sorry we need to so we need to actually determine whether it is a upvote or downvote and then update the field accordingly so in this case we will pass a field name into the statement below so we'll say itself to up vote which will be a boolean value a Taylor true or false and then we will determine the field or updating based on that true or false value you so now I will create a new controller for our votes call it votes controller to RB and we will add a new method called create so this will be the main method that we use in this controller so later we will be calling this method from our JavaScript but for now we'll just set up the default code for this the basic code just to get the overall structure that's working so we want to be capturing the parameter like it passed in so we want to capture the upvote this will be a true or false value to a whitelist some parameters set this to private so will require a require that the vote is passed in and will permit permit some fields so we want to permit the account ID no actually we want to permit the post ID that gets passed in will also permit the up food which will be a true or false value so I can move this one down here we don't need to call it directly so I've got the upload and the post ID and then for the account ID we will set that automatically based on the current account so that's gonna be the signed in user at this point just grab the ID from that and then we will run a dot Save so if the vote is saved correctly then we want to render the JavaScript file but before we do that we should check to see if any if an existing boat is already made so we do have the validation in place to prevent duplicate votes but in this case we want to decide if we are actually creating a new post or we are deleting an existing post so if a post is already made say for example we up upload a post and then we click the upload button again we won't actually remove that that vote it's good to determine if a vote is already made before we do this so let's run a condition and we will say if the existing vote and we're calling the dot size method and the reason for that here is that we're using a voter we're so could be selecting multiple votes but realistically there's only gonna be one vote here but we can basically just say that if a vote exists we want to destroy it otherwise we want to try and create a new vote so if the new vote is being created then we will say if it can be saved then we'll handle some criteria based on that so once our vote is saved then we want to load the post and that post will give us some information such as how many votes have been made up until this point up volts downloads so we will load that after we save and we're gonna reuse this value of this post ID several times here so just assigned it to a variable at the top of our method so we can record so we can set the values for the tool uploads and downloads here at this point so we're not quite sure how we're out putting this information yet but this is useful information to have right now so the set is for now and we'll come back and improve on this method later so for this code we can actually move outside of this conditional so it doesn't actually matter what our vote saves or not we still want to get these values and update our view so we will just record the true or false based on the if our food is saved or not so I'll sign that to a success instance variable and this point we can also wrap this code and a respond to block I don't think it's essential but I'm gonna do it for now anyway I'm expecting this to be handled by JavaScript this method will be calling this when we click on a link so the page shouldn't reload this should just be happening in the background so and then our code to make it a little bit cleaner so we are rendering a partial here for the create method so this crate is in our view a crane you folder called votes and in here then we will create a JavaScript ERP file so just to determine if we've got this working we will do a console log so that will output to the browser console in the development tools so we'll just make a note here of what we're trying to achieve in this files we want to update till votes on the view for that particular post and we'll come back to that I'll later now let's go back to our list view for posts so this is a partially get loaded for each post and if we look back at reddit what we want to achieve is this upvote and downvote links here like this so these buttons that let us I put her down below the post so let's create the mark-up for this first and since we were using bootstrap in our build it will use the bootstrap classes too as to help us with the layout so in this case we're creating a one column layout on the left and that's going to be where our links are for uploading or downloading and then on the right we'll have the details of the post and we will use fun awesome to provide us with icons to give us the up arrow and the down arrow we will have an additional class for the upvote and downvote so we want to hanker some JavaScript off C's later so our spacing is a little bit big here so that's correct is let's keep this one column for all screen sizes so now I'm going to add the fun awesome stylesheet to the header of our page and I'm gonna do this the easy way which is just a drop in the script now you could do this using yarn and I've done that in other videos but I just want to keep it very simple in this video so going back now to our partial let's change the classes on the icons and we can see that our fun awesome is not working so between these two arrows it's up and down arrow we want to have a number here so this number will be how many up votes this post has already got so I'm gonna tweak our layout a little bit here I want these up and downwards arrows to fill the fill space so let's add some styles to our style sheet and we can create a new style sheet for this in fact we'll create one for the posts and the posts will also have the upload download styles we're gonna set our links for the upload/download it's gonna be blocks which should fill the space and we'll set some padding and we can add a background color and see how it looks and we will set our color of the links to black I will also add some styling for a active class now because we're using the s CSS file for this we can embed our classes in this way so you can also do this and just pure CS CSS in which case you just have this all on one line so B dot upload thoughts active if you want to add styles for that so this could be improved I'm not gonna go too deep into the styling of this but we will send our line the content text-align:center and in fact we can actually add that centerline on to the div element itself so let's add a background color to this and see how it looks it's a little bit better but there is a spacing at the top and bottom and for the sake of this video I'm going to keep the styling really simple so I'm gonna remove this colored background this will just remain on white what I do want to do is have a hover State on these links so let's add that now to our stylesheet once we hover we want the color to be I want the color to stand out against the background we also want to have a cursor here so we want to show the user that these can be clicked so just tweak the color should I want to have this a red color so let's use the very basic red color so I reload the page and see how it looks and already that's looking pretty good I want to make this number have full text so make it stand out a little bit so we can do this by adding in class so now let's begin to think about how we can get this functioning this upvote and downvote so we go back to our view so this is our list view so in here we'll add a data attribute and we want to record the ID of the post let's output the post ID and we can actually wrap this whole section in a div and we'll give it a move the data ID onto that wrapping div and we'll have a ID here for the boat actions so this boat ID will be different every time this boat actions ID so it's based on the post ID and we're gonna add a new method here for the score and right now we can just have it returning a zero by default the score on any post will be zero so the score really will be the difference between the uploads and downloads so let's add a note here to remind ourselves later well by default once we call this post our score will be zero to begin with so in order to simplify things on the front end I'm going to add jQuery to this build so just to make things really easy for us so now within our application is I'm going to add a require we're going to we're going to include a vote J's file so let's create this new folder first of all four includes and then we'll add the new file in here both Jas we're going to ensure that jQuery is loaded and I will run a console to vlog just to ensure that we have jQuery loaded properly before we go any further so we can see that jQuery is loaded now so let's go back to our file and in here we will begin by grabbing the vote so that's a wrapper class around this and then within that wrapper class we have the dot up food in this case we will use jQuery to add a event handler on the click method and once that happens then we will well first let's just add a console log again to output the post ID so grab this from the parent element and there's a data attribute there for the ID that we've added so let's see if we are getting this value before we go too much further so say post update update for post and opacity ID let's make sure that we're getting the value before we keep going so it's reload this click it and we can see here that it's undefined right now so if we go back to our markup and we haven't actually got the data ID I thought we had that but we might be removed earlier so let's add this back in post ID and we're seeing the number now which is great so that's working so now let's run the Ajax method jQuery AJAX method and we'll set the URL for this so we haven't actually set up a URL for this yet so if we go to our routes file it's get one added for this so let's make a post method this is going to point to post slash vote so let's add our URL to the Ajax method and we will set the message to be post and we'll pass in the data so in this case we want to pass in the post ID which we have set above and we can also add a method for when this is successful and we'll just run a console log once it is complete and since we have passed the values from JavaScript we can actually remove this food params and we can just assign the value of post based on the prams directly and we could actually have done this using a remote form so that would just pass the form details via Ajax but I think since we have so many posts on the page so many upload download buttons I think this is better to handle this via JavaScript rather than lots and lots of forms on the page so just looking now once we click the button you can see that the insert method is happening so it's recording the vote it's just our view is not updating the the totals right now so the math is getting getting called correctly the votes being created and the totals have been updated on the post - so the backend part is working pretty well so far but the views on the front end are not reflecting the new votes that are being created so one thing we're missing here is the upload value so clean it up a little bit so come back to our JavaScript and we'll need to pass in the upload so that's gonna be a true or false value so we will create a new variable for this so let's extend this javascript code so let's we'll run for both the up vote on the down vote and then we will set the variable based on the class that is attached to the link we clicked in this case we'll say has class up vote and if it has a class and it would be true it is um is an upvote otherwise it would be a down vote so we'll test this out before we run it by Ajax so this when I output the value to make sure it's being set correctly so let's test this out and we can see that it is true and when we click the download' it's false that's good that's working it's part so the values are being set correctly so let's pass them in via Ajax so it's already set and I will should be passing incorrectly so going back to our JavaScript file now for the create GSD or B and here we want to you want to actually update the view so let's start by grabbing the vote actions ID it's gonna be based on the post ID so we want to get the value for the score now play dad so let's add a class for that and we'll set the text within that element will output the score from that post so going back to our model now so let's try to actually set a score based on the total uploads downloads so I'll set a conditional to make sure that is a vote made and if no votes have been made then we'll return the value of zero so if votes have already been made then we will check to see if an upvote is greater than zero and if it is then we will take the out votes and subtract the down votes so we'll get the difference between the two and then otherwise we will just return the down votes but in order to give this a negative value we will just times it by minus one so that will give us negative so if there's one download and no up votes then we want to take that one and reverse it so in this case it looks like we have a problem with the naming let's go back and double-check this undefined method two little uploads so go back to our schema file and see how we've named it and we have named this without the total underscore so let's just update this quickly okay and we're seeing a minus one this other post has a one so it looks like the values are showing correctly but yeah they're being recorded correctly we reload the page we should see the value but we want to get it working on the front end - in real time so let's try to get our JavaScript view working I'm gonna delete the tulip votes down boats as we don't actually need to display those on the front end but we do need to display the score and it looks like I made a typo in this score selector that should have a dot in front of it to select the class and that appears to be working now but the active state isn't remaining so we can see here that when we click it again it is deleting the vote and it is correctly updating the votes but on our view it's not showing correctly so we just need to move this post selector outside of the conditional so that it also gets loaded once a post vote is deleted so I'm gonna click this button we need to show the active State so we know what post we've uploaded or downloaded so we've already styled it so just to show how this works once this class is added it will be highlighted red so this add a helper method so say is uploaded I'm a pass in the post so this crate is method I'm also do the same for the down boat so we'll go to our helpers folder and we will create a new helper for this you so let's create our methods within this is uploaded and we're passing in a post so the first thing I'll do here is ensure that the account is signed in the only people who are signed in will have a vote we're going to load post IDs that we have uploaded from our account model and then we will check to see if that's included this post ID is included so we can probably optimize this further later but I'm just trying to get something working on screen right now so in here we want to load votes based on our account ID so here we can say self-taught votes and we will will pull this based on the up vote being true and then we will just pluck the post ID from those entries so this will create array of post IDs that we have uploaded and we will do the same for posts that we have downloaded or grab those post IDs so again we will create an additional helper method for the down votes and we have an error here it looks like we have a typo so one thing we forgot to output here is a class name that was the reason we are calling this helper method so just to debug this I want to print these IDs to the rails server and we can see that we have got one post that we have uploaded and after we upload it doesn't trigger it so we have to reload the page and now we have two IDs for posts our helper methods are only getting run once the page is loaded the first time so the helper method won't really give us the active State once we click the link we will need to do that using JavaScript let's just correct the name of this method being called now let's try to output the active state class and we can move it as conditional for the sign in into the same line so if accounts signed in and the up for the post IDs include this post ID then we will display the active State and you can see that this is working now for the up vote so let's do the same for the down vote clean this up a little bit reload the page once you reload the page it is working maybe this was cached but it is working now and I'm going to disable terrible links at this point I've noticed a few other applications I built it I run into these caching issues with turbo links and I'm not sure if it's something that I'm doing wrong but I usually unless I really need to other links I usually end up just removing it because it sort of gets around all these problems you run into so let's go back to our javascript file so this was once a vote is saved you want to know they show the active state so that link should stay red so for both the up down boat will remove the active class if it's already said so we can see a diet working and then we want to set the correct the correct state on the link that we clicked so if we click the up vote and we wanted to have a active class and stay red and the same for the down vote so we need some way to determine if the hug vote was created or the down bolt was created and we can do that by setting an instance variable based on the action taken what call this one is up vote now we'll use the prams that was passed into this method so let's have a conditional based on this action so if it's uploaded and we want to highlight the up vote and the same then for the down boat the behavior here is a little bit strange and I think we've got some kind of issue in our code so let's see what's going on but is so it kind of feels like it's doing the opposite of what we're trying to achieve here so it could be something to do with this is upvote value if we look at our rails log we can see that the a book value is actually a string so in this case we need to be treating it like a string and and I appears to be working this time it's actually going the right direction the active State so it's one step forward but we do want to be able to click it and then unselect it again so actually once we unselect by clicking the up arrow in this case we want to go back to zero votes so therefore we shouldn't have any of these buttons being highlighted so that's a different condition in this case we want to detect if we're trading a new vote or we were actually destroying an old vote so in this case if new volt is true then we will run this code which adds the classes but it's not a new vote and we don't want to add the class for active so we can use the existing vote variable here and see if that has any existing votes already so if the existing vote is less than 1 then it will be a new record being created and that appears to be working this time so it looks like we are creating votes and deleting votes so that's all working correctly at this point storing the total value of the votes onto the post that's looking good and the next thing we want to do then is order these posts based on the number of up votes they have so let's go back to our public controller and this time we're going to sort the post and we'll sort it by the score so P dot score in this case posts top score and you can see that it starts at a sending by default so the lowest value going upwards but if we add a dot refers to the end of that then we will get the correct order that we're looking for so let's copy and paste this into our communities show view and here we also want to sort by the most popular posts we'll add a limit here also 20 posts let's click the up vote reload the page we'll see that is now on the top one thing we are still missing here is the up vote on this post details page so let's take the same code that we used before and I think it should pretty much work just by copy and pasting that's in so we have this two column layout again so the right side we will have our comments and our fields for adding a comment the post details and then on the left side we have our upvote or downvote so just correct these values and we test it out we can see that it's already got our vote stored it remember that we have voted already so you can click it and updates so that's working pretty well so the last thing I want to include in our build in is the karma so I wanna add karma to the accounts and basically how that will work is that when we have a post that gets uploaded by other users we will then get points based on the up vote so it's basically just a measure of credibility for a users account how good they are at creating good content so this create a migration and we'll add a Carmen value to the accounts table so by default this will be zero and it is a integer value so we run the migration so let's go to our vote model and after create we will add a new method here so it'll be add karma and it will be a lot like the methods above for increasing and decreasing votes we are basically just incrementing the value for this karma within the account first we will find that account based on the account ID attached to the vote so we are increasing the value and then we are saving the value to the account and I want to display this value at the top of the page so that way we can see what our karma is when we were signed in so we're going here to our header partial within layouts and and we will just output the current account dog karma let's test this out and we should probably wrap this in a div or give it a class of karma and we can also add a little bit of style to this by adding a font awesome icon so in this case we'll use the star icon and I will make it yellow by using the text born in class and we can float that so we can play around with styles more to make this better but I'm just doing something quite simple right now to make a look reasonably nice to the user on the front end so while I tinker around with this I just want to remind you guys if you enjoy this content to subscribe to the channel and check out some of my other builds I have multiple videos where I build different MVP platforms so we're trying to get this aligned with the drop-down menu so I'm gonna float this right and I guess we can move this to the bottom I also need to have a margin to push the Karma value down and move that star to the right so you can take this a lot further and really stylus up I'm just trying to make a look reasonable and I think that's pretty good looks pretty decent so let's click on a few posts to see if we can get this value incrementing and it's not working here at the moment which is a little strange but let's have a look at our model yeah we can see that the boat is being recorded but the value is not going up so let's have a look at what's going on here go back to our model and I think we need to add the value to the increment I think we missed that this increment is by one okay setting the Karma at this time we do the page and then we get our number at the top so let's try this on a few posts and that's working that's pretty good and just to finish it off then we could output that value on the profile of that user and we should also remove karma so when we get download we are taking some of that karma away let's try that out reload we've got two now so that's working back to our profile and we'll add the value to the profile just to finish this out so we can just add this above the creative date or our kick day as we have it here so in here will output the profile karma and then we can also output the font awesome icon again FA star and we want it to be yellow and you can just put the words karma in front of this so that's gonna do it for this video thank you guys for following the long building the reddit clone I want to give a shout out to scout APM for sponsoring this video scout APM makes it easy to debug your Ruby on Rails application and it also helps to eliminate performance issues do check out the link in the description below where you get a 14-day free trial other than that thank you guys so much for watching and I will see you all in the next video
Info
Channel: David Battersby
Views: 3,703
Rating: undefined out of 5
Keywords: ruby on rails, ruby on rails tutorial, rails, reddit, rails 6, tutorial, web development, web app, ruby, rails app, programming in Ruby, ruby language, web app tutorial, rails tutorial, mvp, website, platform, app, startup, walkthrough, coding challenge, Ruby (Programming Language), learn ruby on rails, coding, live coding, programming, build web app, how to use ruby on rails
Id: Rsqj34unV1c
Channel Id: undefined
Length: 46min 48sec (2808 seconds)
Published: Wed Feb 05 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.