Create your First Web App Tutorial in 2021 with Ruby on Rails

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] welcome to the first of the episode in web development with ruby on rails we're maybe using other frameworks in the future but for this one uh we're going to get started and if you don't know how to set up your mac to get this rub and running feel free to look at the card that's appearing at the top right of roundabout now to get started from zero to hero from a new mac or an old back to getting us ready for web development however this episode is going to be about starting your first application so we need a first idea of an application to go with and for this episode i decided just to go with a to-do app it's very simple uh and easy to get started or at least a simple uh ish and uh let's just create it so if i type rails dash v you'll see that i'm on rail6141 hopefully you're all in the same if you're at the date of release of this video but it might be a new version later so i'm going to type rails new and then to do that's going to be the name of our application and in my case i'm going to specify double dash database equals postgresql you may not need to do that here you can just use without that if you want a sql like database but if you want to deploy this live somewhere you want probably either postgresql or my sequel there and stuff like that so yeah rails need to do and that's going to generate in the background now while it's doing its thing generating lots of files i'm going to go through and talk a little bit about what these episodes are going to be i want to implement a feature first of all each episode so that you can get up and running and get it get ready on screen and then i'm going to talk a little bit more about user interface and user experience and maybe making it look nice and other stuff like that as we go forward through the episodes but in general each episode the feature bit's going to come first so if you want to skip the rest about the niceties then you can however this is also about the at least these first episodes about the basics of rails as well so i'm going to be explaining along the way how things work so that you can understand that not just a particular feature as we go along i'll be using examples of banner feature to demonstrate different aspects of ruby on rails so that's all done now and if i just then open this so if i go into cd to do and if i go into my code editor which in this case is a vs code um you'll see a whole bunch of green things on the left hand side here so this is a file explorer and this green is not yet checked in to get a version control and git was going to be using anyway as we go through so we may as well do that but before we just do one final thing here is i just want to create the database so railsdb create that's going to go and create the to do development and to do test database don't worry about the test one we'll come back to that in another episode the development one's the one that everything's going to be included in that you actually add to your application so from there what we need to do is check it into git if you're following along you'll be able to type jst and get git status if not just type git status and do it long hand but this is on my zsh so we have lots of um shortcuts and aliases etc that i can type in here i just get used to them and it's much much faster than actually typing that full line anyway lots of untracked files and it says no commits yet there so what we're going to do is basically add everything so get our dot and then we'll type git commit and then give it a message dash m and the message say initial commit it's just naming this save point if you want to think of it like that there it goes if it's up jesse again nothing to make working to read clean and if i go into my code so everything is white over here so no changed files whatsoever we have a bare bones rails application already and we can just double check that by opening a new tab into the same um to the same directory i've got that set up in i term two preferences if you want to make sure that happens when you open a new tab it stays in the same place etc type railspace s or server doesn't matter which one you type and if i go into my web browser and type localhost 3000 press enter yeah you're on rails so this is the home page of rails by default it shows up here in the log of the web server tab that you basically are accessing the home page get slash which is means home page and then it's being handled by something called rails welcome controller and then hash index um we'll come on to what that means in the context of our code in a little bit but basically that's not our code it's somewhere in in this long url that has nothing to do with us really as far as that's concerned not our code so let's change that then let's actually add our first feature to this application the to-do list itself now the list is just a web page it's a list of things and we need some way of storing that in the database so i'm going to type in a line and then explain what it is so uh rails um and generate g scaffold this is a kind of a newbie way of generating lots of files by default later we'll skip some of the steps in this and make it explicit we'll do lots of separate steps like well generate model and raise generate controller right now i'm just going to get a scaffold up and running so we get this running as soon as possible well scaffold and then i'm going to call it task okay um you call it item you could call it thing you call it all kinds of things but uh i want to be quite explicit about what these things are so i'm going to call it task for now and then i need a list of um sort of columns we're going to sort in the database fields if you like in the form um things about a task so a title a description and by default the the types that it stores in the database is going to be string so if i i can explicitly say the description should be a string here but because that happens by default i don't need to type that if i want it not to be a string then i actually have to change that so in this case i want description to be text okay not not string basically text just stores more characters in the database and then i also want a few more fields uh what do we want to what what makes sense as far as tracking a task well we could think about um whether it's done and we could say a field called done and we could use boolean to say true or false is it done or is it not done well the problem is that some tasks might be partially done um so we can't really use one boolean you could then add two like partially done but it gets a bit tricky then so what we think about it when we have more than two values we want to have some kind of other way of representing that in the database in this case we're just going to use an integer 0 1 2 etcetera so i'm going to state and i'm gonna say it's an integer so our default state will be zero and then the next state along will be one the next date along will be two but we're not going to use numbers in our code to to check that we'll come to a much friendlier way of doing that called enums in a little bit then we want a couple of other things i want maybe a deadline so due at a date time that might be a bit specific to allow times in a deadline i might be a bit micromanagery but uh at least we'll have the ability to do that if it's in the database and we can modify whether you can specify time in the in the html the view sort of area so just remove the extra columns et cetera we don't need with the extra dropdowns we don't need the time and then maybe i also want soft deletion now soft deletion is whereby if i click on destroyer task it doesn't just get wiped from the database it actually stays there but then we just don't show it in future and then if people want to restore those if they make a mistake you can present a different area of application where they can go back and say oh actually undelete that or unarchive it or whatever you want you want to call it so i'm going to call it deleted ad and also call use that date time for that uh now you might think that this also could just be a boolean okay it could just be is it deleted or is it not deleted however i might want to say um for both this and the duet column um i want to know if something was deleted recently and without any extra columns i could actually add deleted boolean and then i could have a separate deleted at column with a date time so i know when it was actually deleted and then query on that but i can get both features both functionality from a single column called deleted app because by default it's going to be stored in the database as null there's gonna be no value there if there is uh something that has a null value and deleted that it's not deleted so we can use that to actually uh represent that in the data in the in the database and in in our code so deleted at durat uh state i where it's at and then title and description seems reasonable for those so let's just actually generate the scaffold that's going to go through and create a bunch more files most of them you can completely ignore there's only a few that we're going to be dealing with in this episode and then we're going to be dealing with other stuff like uh tasks a little bit later so here's all the files again ignore most of them you don't need them for now at least not need to look at them the main one we're going to look at is this create tasks migration file we're going to look at task we're going to look at task controller and then the views so let's explain what each of those are let's start with the migration file migration file is uh let me just open uh is my code editor open yes it is good so let's just open that i can hit command p or command t because i've remapped mine but uh open quick open file or whatever it's called uh that's fine so migrates and it'll find it so in here are what i actually asked for in that line about the scaffold i start as for a string column called title a text column called description etcetera etcetera etcetera uh the only change you want to make here is to change state to have a default value of zero i see its initial state we want to set that up whenever we create tasks other than that that file is fine and then we can actually migrate the database so railsdb migrate okay and that will basically update the database and as the server still running it is so if we then go to on the web browser if you do forward slash tasks uh it's migrations are pending did i not just apply those um real stupid migrate ah yes it is going through now that's fine weird anyway moving on um yes so tasks here is my whole list of things to do so if i then create a new task um yeah there's a problem with this this form this is the thing with scaffolds it generates forms that are accurate to what you ask for but it is a little a little um well let's just say overly verbose in this case i don't want these columns like this although i certainly don't want deleted app to be ever exposed to the user so we just need to modify a couple of things easy enough done let's look at the views so we've looked at the migration file now let's look at the views the thing that's on the screen so in the views uh we're going to look into app views so open up app open up views into tasks and there's a bunch of files the one we're looking for is handy named underscore form an underscore form is used inside uh the new form thing and the edit form thing so if you go back to an existing record and want to change stuff you'll get the same form as you would is if you're creating a new one because they both if you have a look in here it says just says render form in here it says hey i'm just going to use the contents of this file so in here you'll see there's a whole bunch of different html stuff in our case we're going to just remove deleted out we don't need that and in fact for now i think i'm probably just going to uh comment out like this the um the date time for duet stuff i'm not concerned with duet too much in this episode and we can implement that in the future however i do want to have a title description of state and state's going to look really ugly right now um but don't worry we will change that in a little bit so back to our web browser refresh and yes now we can create something in fact let me just let me just comment that out let me just make that make that really simple for us and i'm also going to make the the for just modify the form a little bit it's a text area so i can specify the columns and the rows so coles our specifiers 80 and rows i will specify i don't know 20 and then in the title i'm going to specify the size as say 40 or something like that again refresh the page and now we get something a bit more akin to an actual form so i'm going to create a couple of things so first task and first and then create task good and then press back and create a new task second i'm not going to bother with a description and i'm gonna create a third task third all right three tasks all well and good and everything works in our application are we done well to get the feature initially created that perhaps but i'm not happy that this shows a deleted column here as well and other bits and pieces so why don't we just modify this to look a little bit a little bit more appropriate first of all i don't need show edit and destroy buttons next to everything i perhaps don't even want destroy to be able to be accessed from this page i'm just looking at a list of tasks after all so let's go and look at that particular view so this is the form we're not looking at the form anymore let's look at the index page this is the one we're looking at when it's showing us uh basically all of the lists this is our to-do list so first of all i wanna i don't wanna show button what i actually want is the first thing to be a link to show and then i'm just going to delete uh that and then just refresh but now it's a show for everything well that's no good so instead i'm just going to change the basically the show name here delete that and then type in task dot title and then now we should have the title being a link to the show page and the show page is just the page where you show all the details about the task uh when we style this is gonna be nice and look in the middle of the screen and maybe show other things like comments in the future and stuff like that but for now it's it's just a link and description i don't want that as a separate column that's just no that's my technical description so all i'm going to do is collapse that into the original column i'm just going to basically put a break in here and then just put that like that and just indent everything a little bit so that everything looks a little bit nice in fact let's just put that break on the end of the last line there we go so a link and a description in the same uh column uh but i then need to basically remove the header as well otherwise everything will look wrong and then i again i'm not going to want the duat column for now we can add it back later and i definitely don't want to delete that column so we're going to take that out do that as well okay delete it out okay and this color span now is down to and there we go so it's very very short indeed title with a description underneath if it's descriptions provided and then a state column mistakes very ugly we're going to fix that now at least shortly first of all i actually just want to comment at the destroy and i think i'll comment at the edit as well okay yeah so there's always a link on the show page to go to edit so i can always do it that way and destroy will come back to as far as that's concerned about deleting it it's probably going to go onto the edit page as well so uh edit in here i suppose something like that or the show page it'll be it'll be a link somewhere so for now we've just got a list of tasks and it's state let's talk about state uh so let's just get that neatly formatted so let's look at the next thing in the files that have been created the task okay this is a file called a model that's got rb and let me just open the controller and the views as well so we've got everything along alongside each other so i can explain mvc a little bit so and then the roots file okay so when you request url in web browser forward slash tasks it's going to go to your controller but it's going to do that because in your roots file or your rats values you're american it has a line that says resources tasks so that generates a whole bunch of urls that are available for people to actually request from your application so if i type rails routes it's going to show me all the urls that your application will respond to and there's a whole bunch of different stuff okay but let's just actually shorten that a little bit and append this by typing a pipe character that's uh basically next to your enter key and shift uh shift backslash on that keyboard and then type grep task so basically filter this to anything that just mentions the word task much shorter list much easier much much easier for us to actually deal with so on the right hand side look here first there is a controller which is this first word then a hash and then the action which is the second word what it means is anyone who goes to this url right here will get sent to this part of your code so in this case get which just means a regular web browser um you know web page get a post is when you submit for form details we'll come back to that later and don't worry about patch push and put and delete for now so if we get the four tasks url don't worry about the format bit go to tasks index so go to task index we then go to tasks controller which is that first bit uh the first bit in that root and then go to index and that means go here this uh is then going to go and retrieve a whole bunch of stuff from our well our model which is our database essentially task.org so it's going to go in here it's blank by default you get a whole bunch of stuff for free and all method is basically saying everything from the database that turns into a database query that says get everything from the tasks table um and give me them please and then it adds them into an instance variable the instance variable is then available in your views so if we go into the index or we've just been editing you'll see there's the instance variable and then there is a built-in method says each i mean this is going to create a loop and then inside the loop we need some way of referring to each one so each one it has a name called task it's a local variable and inside the loop we can then say we can use that task to refer to like the title of just this one task okay and it's going to loop over those for every single task you have that you have in your database for this particular case so the model contains everything about the data that's held in the database really in its relationship to other models for example if you have comments assigned to a task you might have them a reference to them in this file we'll come back to that later task controller is really dealing with going and interacting with the user it's going fetching itself and from the database it's going to present the view the correct view to the user and you'll see uh by default the scaffold shows you above each action which url it is happening and it has json built in ignore the json things for now we're not going to cover those in this episode basically as we're asking for html here and you can see if we want to have a new task we can just type for tasks for slash new in the web browser and it'll come here because of all the stuff in the roots file we're going to make one major change in the roots file and that's going to specify the home page to be the same place that we've been looking at so home as our route to and then we're going to type in quote marks and then tasks and then hash index okay and now if i go to the web browser and just do that we get the same thing so this is our home page now it's our list of tasks cool so now all i want to do is do two things before we get to to the end and that is first thing is going to be about um changing the state thing to be less ugly okay so we need an enum for that so let me just go and add that to our task model to do that it's pretty simple if i just type in here enum and then the name that we've created at in the database state in our case and then create curly braces i can then basically create a friendly name for each value that we have in this state so for example i can say i don't know initial i'll probably rename this later but initially it's fine for now started as one and then finish or done as two all right and that's it if i then go back to my web browser and press refresh you'll see it says state initial so if i then go into let's say second you'll see in the edit form we don't currently have that state drop down remember we removed it so if i go back to the form and if i then go and allow um this to be state i'm not sure if that will actually work by default without some more changes let's just give it a go yeah it doesn't it thinks it's supposed to be a number field and it's not supposed to be number field it nouns needs to be a drop down so here's the modification i can change that to be instead of number field i can just be a select which means a drop down and we call that obviously the same name but now we need to because it's a drop down we we don't want us to drop down it's not automatic what the values are in that drop down so instead we need to go and ask the task model to give us all the states and then we want the keys for those states ie the friendly names and then give us an array so we just can just chain the methods along like this and if i do that we get this form so we have initial starter so if i just change that to started and update the task and go to back you'll see now i have state started still not very friendly as far as how it looks but we'll get to that as well again date time select i need to worry about still so i'll just close that form off and what's the next thing i want to look at i think soft delete is the next thing i want to look at so i'm going to go into the edit file and i'm also going to go into index and i want to just copy and paste this particular line right here uh because we're going to just use that in the edit thing we're going to say show the back and i think that we can just put in an extra line and unlike this so i can say uh in fact this is wrong file i actually don't want it in edit after all i want it in show okay this is going to show all the details and then i got a link to edit down at the bottom and i've got a link to destroy and then uh probably i just want to put a break in there and put back so if i go and click on it here now uh for example third i can then say oh it's gonna okay yeah so i'm referring to something in the task i need to just say that to be the instance variable task there we go so edit and destroy so if i go in and click to destroy right now are you sure it's going to pop up and then it's gone it's gone completely from the database it's not there anymore and if i want to undo that later that's going to be a problem because it isn't there anymore so we need to implement or at least i want to implement soft delete so i can go back later all right so how do we do that well we have this deleted at column which is a date time and it's pretty useless as it is we need some way of thinking about that inside the application so let's look back for the moment at our task controller down to destroy this by default is going to just destroy the task as we've said we're going to change that so what we're going to do to change it is say deleted at instead of destroying it we're just going to set the deleted at field to time.now i literally our current date time down to the microsecond or whatever it stores as doesn't much matter and then we're going to want to try and save the record now right now it isn't doing that because it's expecting us to just basically uh it's gone and then we just redirect ignore what this respond to thing is ignore the format json line just look at the format.html basically redirect the user to back to the tasks url now the tasks url is in the roots you see here it says tasks these can be appended with underscore url underscore path depending where you are and they'll take you back to this which is our list of tasks so it basically says go back to the list of tasks and given notice that the task was successfully destroyed and if we go into the index file at the top you'll see there is a notice output here by default it's false but that's the green message or red message potentially that you get at the top of the screen telling you what you've done you don't have to have it there but it's nice and friendly for the user to know what they've just done just in case instead however what we're able to do is just let's look up here you see respond to do format and then if task saves do something else something else all right so what we're going to do is just take that bit inside the respond to do format i'm going to paste it down here okay in fact uh no i'm not gonna paste it down here i just want to take the whole thing the whole response i'm just gonna modify it a little bit because we don't need a lot of the stuff so ignore this existing block down here and paste in this and then we're gonna just do really remove the else stuff because if it doesn't work then well there's no should be should we know what reason it ever doesn't work put it that way and then we'll just make sure uh we'll just say um soft deleted uh well archived shall we say that's what successfully archived and then let's get rid of this original block okay right so we're setting the deleted ads i mean now and then we're going to basically ignore the respond to if task.saves it's going to try saving it if it's successful it's going to actually redirect us back to the actual task we don't want the task in this case we want the tasks url all right task was successfully archived now if i go back to the index form and let's go to our second one let's go to second and we press destroy it's going to say are you sure and it takes us back and says task will successfully archive but it's still there it's still there because although we've set something in the database what we haven't done is talk well modified our view and our controller to basically output only the things that are not deleted right now if we look at our controller at the very top we're basically going getting all tasks and outputting it and that's what's looping through in the index now we could just try and do some other things in there uh what we need to actually do and discuss now is scopes so let's look at the task thing scopes uh as it might sound are ways of changing the the data that you get um so that certain things are included or certain things aren't included there's a two different ways of doing that one is default scope okay default scope and we uh are basically going to apply that to everything if you use this and the syntax has changed in recent versions so let me just see if i remember this off the top of my head where um let's just say deleted at is um no okay uh let's see if that actually works and i've remembered yes it does work okay so to explain this when we ask for all in the controller the default scope always applies if you specify one so it's basically saying get me uh or basically append to all of the things i ever asked for this bit this where deleted at is null so if i wanted to i could just go in here and type this the same thing where deleted at is null but it's a bit of a pain having to type that every single time so instead we can apply that as a scope in here works fine there are some gotchas however with default scope you have to remember every time you ask for this uh the default scope will apply i if remember rightly so if i went here and said um you know task dot where this delete is null yeah that's fine but if one of you a not null it comes up with nothing that's weird because we've set we've set the date right we set the data in there so not null means there's an entry in the database so it should appear the problem is again the default scope always applies so you're literally saying go and fetch me the things that are null and then of those the things that are not null so it it just brings back nothing okay so that's that's important so instead you can leave it as task to all with that gotcha in place the other way of doing things is to add a scope a named scope so for example we could have deleted okay and this has a slightly different syntax but it's pretty much the same other than the starting bit where delete that is not null so we've now explicitly got something called deleted and if i then type in here deleted i'm again i'm not getting anything because the default scope is still there so if we just comment that out now i can see all the deleted items so again continue to be aware of default scope the other way of doing if you want to leave default scope out is to create two named scopes so instead i could say uh i could say not deleted i suppose here not deleted and then you'd have to say here like not deleted so uh yes uh we have to be a little bit careful oh i have to change it here uh is null okay so not deleted is null so there we go uh however um that again is going back to being a burden here instead you might call them active okay and again we'd have to talk column active here and away we go okay same thing applies however for now i'm going to use default scope just remember that it exists and we have to if you do have it existing like this then of course it's going to work but if you want to get to deleted then you can't just do deleted as i said before because nothing will come back you first have to say unscoped dot deleted and that should give us the things we want we have to unset the default scope all right other than that and other than that we can just use little handy terms like this uh whoops uh handy little um basically scopes to get whatever we want we have lots of these things like for example we could have one that said um i don't know uh due today okay and then we'd figure out what we needed to write in here for uh things that are due today uh for example it would be something like due at is uh less than or greater than i remember the syntax for this thing i'll come back to it later but then say um i don't know uh time.now i don't know minus 1.day or something like that that's wrong but i need to go and actually do that later but we can have these so that we have these handy little things we can refer to in our controller and just say for example if we have a separate controller just to show today's today's stuff that's due in our index instead of just writing this kind of stuff we can just literally write something we've named for example dot due today and then we don't have to worry about any complex code in here because we've written all in the task layer so that's soft deletion and that will actually work once i've restored everything back to where it should be so that's the all and everything works as it should all right so now we've got a to-do list app we've got the both to create uh edits and delete stuff we've got for example we're in here and create edit we can just type in first long description of something that should probably whoops probably be lorem ipsummed ipsum and we can just update the task and back and i think i don't even want to go to the show viewer here actually so when we go to the controller if we have a look in here when i create something it says go back to the task and say task was successfully created i think i just want to go back to the tasks as well to be honest tasks url oh can i just go back to tasks do i need to actually specify url uh let's just go and um edit oh in fact this is just for create so new test test uh whoops test test creates yeah it's going to need a tasks url okay and if i resubmit the form yeah it comes back here so task was successfully created and uh if i just do that again it should just come test test test test and create task and it'll just go straight back to the top yeah i don't want to really see that show page too much unless i actually explicitly click on stuff so that's all cool now what i want to do is just change this state column it's very ugly i'm not going to want to see state initial like that i'm going to want to see perhaps some kind of icon representation of that now we're going to be implementing in probably the next episode tailwind now i forgot tailwind css.com i think it is um yep here we are you'll see if i press command k on here there's a shortcut it lets us basically look for anything so i'm just look for svgs uh there is i think like an external um let's see documentation there's like external sort of stuff in here for sort of quick icons that you can actually get together let me see if i can find it um interactivity no svg maybe i know it's over here on resources at the very top and then there is icons hero icons so mit license high quality svg and this is really kind of nice so if i look at for example let's just do a command file f and then check mark so we have a badge check and then we can just continue pressing enter check circle check let me just actually just use this for now so i can just copy svg there's no images to actually license or anything it's obviously mit license you can do anything you like but if we go into the index and then where it says task state we can actually just change this now so we can modify the list a little bit we'll probably move this into its own file later because it'll be like we'll need to probably add drop downs for this to be able to change things by clicking on the icons rather than just the names but for now it'll do we just want to have something nice and neat so we can say instead of task.state we can say um and remove the equal sign meaning we're not outputting anything here uh we're actually just having a loop or well actually not loop in this case we're actually going to use an if check we're going to say if task.state can we just refer to that by its enum i think we might be able to initial will it let us out have that i don't it may not do uh if not we'll quickly fix it and then we're just going to paste in the svg okay and i'm just going to indent that so will you let me do it probably i didn't think you would i was hoping it would be really nice and automatic uh so let's just say if the state is uh equal to uh initial or something like that i'll refer to that later will that actually work now about how about just initial as a symbol no you won't work either let me do this properly whoops i just forgot to remove the dot initial from this side and uh yeah we can just say is it actually initial then we can just look at the tasks and you'll see that we have an icon it still is looking odd we'll we'll do that we'll deal with that when we come on to tailwind in the next episode however for now we can just then say uh that uh we can do an elsif or we can just do ifs in this case so we can just do if and then again this is probably why we're gonna move this off into a separate file uh what's the names i gave them so started and then done okay and let's just look for a couple of other options on hero icons so started well who knows uh maybe a clipboard or something like that uh just for the moment uh clipboard clipboard check maybe um clipboard let's just uh do that and let's paste that in and indent and then for done uh sorry for initial um what i want for initial maybe just a circle or something like that it doesn't much matter circle dots circle exclamation mark just like a a circle please that would be nice uh no there should be something along those lines i would have thought and i just added them as an inbox symbol for now so if we go into first task and then press edit we can change the drop down to be i've started it and update the task and i do need to just change that one thing in the controller there so we did the same thing on create we want to do the same thing on update here so it goes to the tasks url and not back to the task uh just tasks url tasks is actually updated etc and then we just go back so now you see there is one that's got a clipboard so that's the one i've currently got it started as and then i can just go edit this one maybe then say edit and then say this one has been done and whoops i forgot to actually complete that done and then update task so now i've got three different states and they're represented as icons and then what we'll probably do obviously when we get to the styling of this is just move this into the middle of the screen and space this out nicely and format formatted and stuff like that so everything will look pretty good but right now we've got a working application we've got the ability to create tasks edit them update them we can soft delete them we can um basically change a lot of stuff like that and we have this nice friendly way of just basically getting access to just the ones we want so for example i could just request the ones that are in the initial state or the ones that i started or the ones that are done and do stuff like that for now i think that's it for this episode next episode as i said we're going to come on to starling hopefully you've enjoyed this if you have do put some comments down below with any questions you might have and we'll cover it probably on the next episode i hope to see you there thanks a lot for watching feel free to subscribe down below and press the bell if you want notifications for future episodes otherwise yeah see you next time
Info
Channel: Code Build Repeat
Views: 1,200
Rating: undefined out of 5
Keywords: web development 2021, ruby on rails, ruby on rails tutorial, rails tutorial, rails 6, how to use ruby on rails, web development, learn ruby on rails, build web app, ruby on rails 2021, ruby on rails for beginners, ruby on rails project, todo list tutorial
Id: jfqNQdqSAfk
Channel Id: undefined
Length: 40min 1sec (2401 seconds)
Published: Sun Sep 12 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.