Ruby On Rails Crash Course 2020

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey guys welcome to the ruby on rails crash course this is a course to kind of give you the scope of what ruby on rails is like in 2020. first off i want to thanks traversary media and the team there and the channel it's been such an inspiration to see that channel thrive and i've learned tons from it um the javascript particular it's been an eye opener in terms of getting javascript in my head after several failed attempts so very excited to be on the channel and supporting the cause so first off i want to say that that and second if you haven't heard of me i have a youtube channel called webdeskcrunch you can just find it on webcrunch at youtube i also have a blog that basically every every article or video i publish is typically followed with an actual article so the website's web dashcrunch.com so be sure to check that out if you're interested and more ruby on rails stuff javascript and css a lot of front end and back end what we're going to be working on in this video is building a basic food log app and ruby on rails is a complete framework built with ruby of course and another language called rails which was created by david heineminer hanson who works and co-founded base camp so ruby on rails is used by tons of companies you've heard of some of the biggest you've heard of too so github shopify those are probably the biggest apps out there that run ruby on rails today so check out the actual website there's a lot of great guides and the api is a great source to find more information about tons of stuff available to the framework you can also check out my youtube channel too if you're just new to it and when i get deeper in the scope of finding more about the framework website to check out also is my friend's site called go rails what i would recommend if you're not if you haven't installed rails yet is to check out the guides on this site i'll link to it in the description depending on your system you'll need to install rails a specific way it depends on ruby of course you'll need to install ruby and typically with those you need version managers and so forth so if this is all kind of jumbled to you i really recommend taking a look at these documents and and getting them installed i won't go through that in this video that would be an video you know of its own to kind of get under so i would check out that um i'm running this on a mac os system and i don't believe i'm on catalina yet but i'm on mojave i might be on catalina i can't even honestly remember but i'm going to run this on that i am on the latest version of ruby and rails so we'll be running bleeding edge there but otherwise if you just run i don't even older versions this should work in theory we won't be using some of the the new tech available in the framework because that's just there's just so much to cover but i want you to understand at least the basics with this episode under the hood i'm also rocking bulma for now just to save on some time and styling i'm a really big fan of tailwind css but to do that in this video would kind of take over the video in terms of getting the front end scaffold and bulma just kind of brings some pre-defined styles to the table so we'll use those but we're going to be creating a food log app and at its core it's very simple but a lot of these operations will kind of give you the scope of how rails works as well as understand the ins and outs of the framework ruby on rails in particular is an mvc-based framework which means vinyl view and controller those three things are separated but they do talk together and typically in the model layer that talks to a database the controller layer kind of does the request so the whole request cycle of the app and the view layer is what you actually see so the view the data that gets printed and you can uh interact with as a user and i just want to walk through the app quick you enter a number for calories proteins carbohydrates and fats i'm kind of a health nut so this is kind of ringing true to me but when you add this data it gets added to i'll just do it so we'll say dinner like maybe i ate a ton of stuff for dinner um 40 60 30 just some some random break down there presents this new entry as you can see in the url it's an actual id that gets added there's tons of ways to kind of configure how that url would look in the app we won't go deep into that because that's just stuff you just learn as you go but this is a an icebreaker for that but essentially once you create that entry you get to see it here on its own page if you wanted to go to the root path of the site you see all your entries for the current date so if you were to add several meals here you'll see all of them in this view and then each day you visit the app you'll see that for your specific day you might be asking well what if i want to see all of the entries i've had well i created a view for that that are grouped by the date itself and then you display basically an added format of each of these meals so we do some some calculations behind the scenes that present this stuff in an ad hoc fashion so for each day you'll get a breakdown so if we were to add a new entry for tomorrow there'd be another whole new august 28th entry down below with a group of grouping of those meals all that plus some testing is in this video it's gonna probably be a kind of a long video so just brace yourself but i want you to know at least the ins and outs of the framework so let's dig in i'm going to assume you've installed rails using the guide that i mentioned previously like i said i really might recommend just walking through that it should get you up to spec windows machines are a little bit harder to get ruby and rails installed on i know windows has a subsystem for linux now at least modern versions that you could probably use and get and started with this guide again mentions that so definitely check that out if you are a windows user so like i said i'm going to get started quickly here we're going to get some bulma into the mix i'm going to remove some of these tabs i have this running locally right now on a new app but we'll create a new app and rails is basically done via the command line i'm going to go into my coding path and i'll do a rails new and then what could we call we call it food log [Music] and that's essentially it once you have rails installed on your system you can run this new command and it'll generate a whole app for you that's just basically ready to roll so there are perks to using frameworks and this is one of them it kind of just generates the stuff you need depending on what you need and you can pass in options on like almost any option under the sun when you create this stuff so definitely read the documentation if you're interested in learning more there's just so much to cover so this video will be very brief in in those aspects under the hood with rails 6 is the current version that i'm using webpack is basically by default in these apps now it used to be a different ecosystem where you use a lot more jquery or vanilla javascript what's different in these apps is that it's more dependent at least on the javascript layer of webpack based builds so we won't get into too much of that in this video but it is something to be aware of that you can totally run front-end frameworks on this framework itself if you want to and honestly to be frank a lot of apps out there now run ruby on rails as the back end of their app and like something like react or vue.js or svelte on the front end and that's up to you if you want to do that with that comes different conventions to adhere to so ruby on rails is very convention driven so there's it's a basically opinionated by design and that's part of the perk of using it because you can scaffold out a lot of things very quickly and get an app running in almost no time let me go and do the cd into the the actual app we're going to run i'm using a fancy terminal theme here so just you know don't worry about it too much but it just gives me some readouts of where where i'm at with using git and whatnot so we will use get a little bit in this but not too much just to kind of keep track of where things are at and just kind of make changes so when i push this live you guys will have the actual end result so you can refer to it but typically if i'm working on a typical app at each milestone i'll do a commit and and add those changes just so there's some history there to go back to if i need to actually what you see above here is the actual look and feel of the app in terms of files and folders there's a lot to it at first it's very overwhelming and i promise you the more you work with it the more you'll just understand where things are and how they work together but at first glance don't worry if it's it's a little too much to take in if i'm using vs code for my editor we'll see basically all of the stuff ready to actually version control so maybe i'll just do that so that's not green so get add the whole stack basically git commit in it and if we were to boot up this app at this point if we say rails server in our command line within that app and i'm in that app if you want to see if you do pwd we're in that app now if we do rail server we can actually boot up that app at its current state which is basically a vanilla ruby on rails app by default ruby on rails apps run on localhost 3000 so right here is what you see that as if i refresh you'll see the actual welcome screen of ruby on rails it'll actually print out your ruby version and your rails version which these could be a little bit behind already so at this point we're at a place where we can think about how the app's gonna work and typically that's what i'll do when i build an app so i'll think of the the underlying data structure or problem i'm trying to solve and in that case so in our case we're trying to make an app that is mostly a journal entry app so there's no user authentication or anything right now and that's something you can add later and definitely check out other videos to understand that on my channel there's a ton there this is more of let's get that entry taken care of we'll get the calories the proteins the carbohydrates and fats and then the actual date it was created on added to the app so we can you know create that low so we'll do that now and what's great about rails is under the hood there's this entire cli structure so the rails command is the biggest helpful command you'll run into on a framework like this if you just type rails in your command line you'll see all these functions fall back and it's just almost endless of what you can do so again another overwhelming thing of such a large and mature framework underneath all these commands we've got available to us a way to generate things so if you look at in the g section which actually doesn't show here which is kind of interesting i thought it would but there is a command called rails generate actually it's at the very top it's the most common one and it has a shortcut of g if you want to type less so what we'll do say rails generate or in short g we're going to generate our first what's known as a model so the model layer of the app so we'll say model entry and typically in a rails app a model is a singular word and typically capitalized so what we'll do is pass in a few columns that will actually be on the database layer now when a rails app is first booted up in default mode um it uses sql light 3 under the hood and you can use almost any database type under the sun for the rails apps but typically it's postgresql mysql or sql lite and sql lite's fine in development mode but in production you'd probably use something like postgres or mysql so a little behind the scenes info there it's not important right now because we'll be doing this in development mode but all that's taken care of in the development mode which is great if you recall on the screen we had that form and what i want to add are these columns that are going to be the fields of that form and these are going to be database columns in the database so essentially this will be data we store in our database and you can pass in the type of data it is from this command line so in theory we'll have all this stuff ready to rock and roll so a lot of rails developers will shine away from the scaffold command and that's mostly because it generates a lot of cruft under the hood um scaffolding in rails is the quickest way to get up and running with the crud based operation so crud is create read update and destroy so that's something you might do with the typical web app so when you're creating say a blog post you'll create the post maybe you want to edit it you'll go edit it and then you update it at that point oh if you want to delete it then you'd go delete it so you could do all those operations with the rails app and honestly it's it's boiled down now into these apps with one scaffold command like this to get that functionality what's great about this is the speed what's bad about it is the amount of files it generates and maybe cleanup you have to do later which is why it's kind of frowned upon by purists in the in the field so teach his own i'm going to do it for the sake of this learning exercise we'll go through and kind of talk about each situation and why it makes sense to do it the way it is but you'd see this video would be quite long otherwise if i didn't do this command and you'd see why in a second so we'll pass in one called meal type and it's going to be a string type in the database the column name is to the left the type of data is to the right so we'll actually pass in calories and an integer and then proteins will be integer and then carbohydrates integer and then fats integer all numbers for those because we'll just enter those in you know as numbers as we see fit it won't be perfect in the sense of like what you'd actually ate that day like the actual food item but it will be the caloric macronutrients makeup i guess you could say so let's go ahead and create this scaffold and you'll see what it does here when i run this i want to make sure i spelt everything correctly first so we'll run this and you'll see it's going to create a ton of files for us which is the bad part but also the great part if you look at this we have a migration file this is going to be the file that we can either modify fields in the database with through my what's called migrations so these commands you run to either go back in time or forward in time with your data which is very handy and then our model layer and then our test layer uh our routing gets added here automatically notice it's pluralized here so that's something interesting when you pass in the singular version here uh by the power of ruby and rails they're pluralized in the sense of where it makes sense so for our routing entries is going to be the plural form same for controller and the views so there's a new view folder called entries in this case and then various other things j builder is just a way to render json in a rails app it's not anything we need to be concerned about in this video helpers are handy methods of a handy place i would say to extract things that you use within your view layers typically test units so unit tests will be basically here we'll do system tests and controller tests coming up for this just to show you how that works in the ruby world tests are the you know emphasis of ruby itself ruby's very dynamically typed language it can be very loosely typed so there's no like actual typing like a language like c or c plus or something like that um so in this case we need to write a lot of tests to account for things and that's kind of just the way things are a lot of rubyists practice the tdd or test driven development we won't be doing that per se here but it is something you maybe want to read up about underneath the hood we've got assets sas is already installed by default we don't have to worry about that which is great um and then for scaffolds this generates a scaffold css file or scss file we don't really need that but i'm going to just show you what it does here in a second so if we were to go to our app at this point we've got new files and the first one i'm going to show you is the migration file this is what creates the new entry table so it's underneath the hood rails has this dsl language or domain specific language that talks to an actual database for you so you don't have to sit there and write my mysql by hand or anything like that and that's i think a big reason people gravitate towards a framework like this is that that intermediate layer of just kind of a humanistic way of writing data out that creates in this case a table with these fields on it i don't have to touch any sql and it's just it's just done now these are our fields we typed in that command you notice and then we're going to create an entries table which is plural notice that too and then by default when you create a new table there's this field called time stamps that creates a created at field or column on the database and an updated ad column by default those come with each of those new commands whether it's a new model or a new scaffold so those get that by default now in this layer you could set some defaults if you wanted to like calories would be zero by default or proteins with zero i'm going to leave it alone just to keep things less complicated but this is where you would essentially interact with the data layer and these are meant to be changed and you'll see in a second a file that's not meant to be changed called the schema which is actually kind of a visual representation of the database at its current state when you run a certain migration so i'm kind of blazing over this stuff there's a lot here to unpack but i just want to kind of be thorough where it makes sense so there's all those files that were added our main one that we'll be working in is the entry model class we'll add some stuff here that makes sense coming up and then our controller class because we scaffold it out i've saved a lot of time in creating this these files by hand essentially what's happening is all of these actions they're called actions are essentially views in the app so if we go down to our views folder in this folder you'll see all of this kind of the same naming conventions for these methods in this file so there's a show view there's an index view there's a new view and an edit view there isn't a create view because just the way rails works a create is what would be the post requests in a given rails app so that happens all kind of via a form typically and then the same is true for update requests so those all kind of are based on the form you're working with and then destroy is going to be where you actually delete the file or record in the database so it goes and finds it and destroys it and these all have these respond to blocks in these actions and what's neat about these is you can respond to almost any file format typically in a rails app it's html but you could do json and even javascript rendered responses here so if your app's a front-end app you'd probably do json more than html here by default and with that said rails itself has an api mode so if you were to create a new rails app brand new and type dash dash api it'll actually set itself up for javascript driven apps by default so again another reason people reach for it and we'll go too deep here i'll get kind of in the weeds here in a second once we get into the view there but rails has its own conventions with html as well as you see these are called html.erb files so essentially it's a neat way of saying hey i can write ruby in these files and that is what we do so any entry that comes back from a controller layer which is where this is all derived from so notice how index correlates to this index file in the views we're actually grabbing that instance of entries from here so those are all connected and then we're looping through this is ruby and then printing out the meal type the calories proteins carbohydrates fats and then some actions we can perform on it whether it's to go to the show path or this file and see what was saved or to edit that file we'll go to this file and so forth under the hood rails comes with these url helpers are linked to helpers which are essentially a neat way of saying it creates the ahrefs in html forests that have these paths pre-baked in so we don't have to remember what actual routing would be and it's very dynamic in the sense of things and if you were to want to understand where those routes could be useful you could visit a certain url in your rails app locally and see all the routes in your app it's it's super useful i'll show you that in a second once we get going here so essentially that's it in terms of structure all of our assets in terms of style sheets would fit and underneath the hood here there's that scaffolds file that's in here by default i'm actually going to delete this because we're going to reference bulma particularly in this app and i'm actually going to change this one to a scss file since if we were to write any specific sas i don't think we will we would render that here there's a lot to unbake in this folder but honestly i don't want to spend too much time there it's not that important at this point i will point out that there is a folder called javascript here and this folder is where you would import any of your es6 equivalent kind of javascript this is where you could add pretty much any framework under the sun and there are specific commands in the rails app that allow you to do that if you want to do like react or view or spell like i said in the beginning again beyond this topic of of this basic crash course i just want to get you familiar with the basics of the framework first and how rails works in terms of http requests and editing data and and so forth so forth so if we were to go to our actual app now we're going to be presented with an error so i'm going to say rails server again actually we're running a server already so i'll we're actually told that if we go to the app it's going to get it's going to say this and what's happened is because we created that new table there's a new migration in the stack that the app knows about but it hasn't migrated yet and that's this file here that we checked out before so it's got that create entries file so what's unique here is that until we migrate will this you know app boot up so we can actually just do it from here or if you want to be i guess you could say the old way is rails db migrate from the command line this is the way i'm used to and it's quicker in a sense so you can run that or click that button in that the web view if you want that's totally fine but then it prints out a time stamp of when this entry was created and then it goes ahead and migrates the table so that at this point that table is created in our app and what's neat is it generates this file i mentioned earlier called schema.rb and this is a ruby file that's essentially a way to just visualize or see what's going on in your database at any given moment this isn't a file you want to change it is one you would just reference in a sense and notice it has time stamps that change basically as you add more migrations and you wouldn't really add a migration by hand that would be something you generate from the command line just to save yourself some time you can generate anything under the sun in a rails app so raz generate model so then you can just do like a new model you could do um i'll do short for controller tests anything like that you can generate a helper all those or even there's even mailers baked in this framework so you could send emails like transactional emails if you wanted so that's all baked in and that's super useful uh as we migrated we could see our app again but we won't actually see that scaffold we just created that entry scaffold so let's go to what will be called a routes file and you can find your routes file in your config folder and there's going to be a file called routes so if you remember that scaffold we created this there was a line called resources entries that's part of how our routing is working i'm going to delete this line for now so it's clear here we set up our app to draw each route in the app based on what resources we have available and a resource typically points to what would be normally a model but you can create one-off routes if you wanted to they're just like get my route something like that if you wanted there's a ton of stuff under the hood you could do but the gist is that this one liner creates what i'm about to show you so we'll go to this specific url rails info routes notice all of these here were added and you can check out this stuff down here this is all kind of stuff that comes with the typical rails app these days but you don't really need to worry about it for this video that resources one-liner route created all of these i guess http requests the wall routes so in this case we've got a get a few gets patch which is an update put another update a delete and then a post so all these correspond as you call in the controller to those same naming conventions so again a very convention driven framework so entries index corresponds to entries path entries creates would be entries it would have the same thing we just pass a post request through entries new will have its own little url helper so new entry path now it can be url as well so the difference here is path is relative so it wouldn't have the full website url in there whereas url would be absolute which would actually have the whole website path you'll need both in a typical app some some routing some like emails for instance need that full url but in an app you can use the actual uh path version so this all comes for free thanks to that one command and that's super valuable so you don't save yourself some typing there's a lot more to unbake into or unpack into the routing again i'd recommend checking out the documentation or of course my channel if you're interested well i've added our routing we need to actually go back to add a root path so right now our app boots to the welcome screen in rails which is part of the gym it's not actually part of our app but it more or less is part of the gym in the rails app and i forgot to mention jim so why don't i do that quick within every rails app there is this file called the gem file and this is actually just kind of a ruby convention it's not necessarily a rails convention but this is how you can install dependencies for your app so each app by default comes with what you see here and some of this is relative to certain environments so in our development environment we get specific gems in our test environment we get specific gems and in our main environment which is anything up here we get all of these that run in pretty much every capacity so what's neat about this is if you need a specific gem for specific tasks you can add it here and run this command bundle so bun bundle install is typically how you would install a gym if you wanted to add a gem specifically so i know there's a gem called i just added it to another app gym ad twitter bundle ad twitter excuse me so if you go it goes and fetches that if you come from javascript land if you know maybe npm or node um or yarn in particular you might know how this convention works i would be i would argue to say bundle or bundler is where those gain inspiration from so this is the ruby way um but it's hearsay so just think of it kind of like that in the sense of how you install dependencies but you don't have to do it the same way a typical site i'll reference rubygems from is right here it's rubygems.org you can search any gem there's a ton that are still pretty lively and some that are outdated since rails is quite quite an old framework but it's still very mature and well polished i mean shopify and github are using it so i'd say that's good enough for me process of adding a gem can happen from the command line like that or you can go and copy and paste the actual name of it from like your github repo and add it here and it'll go ahead and fetch it now when you add a gem manually you would need to run bundle install and it'll go fetch the dependencies for that gym and that gym itself now we don't really need the twitter gym in this specific case so you can actually just remove it and i'll save that file and just run bundle you can run just bundle if you want in this case and it'll do the same thing instead of bundle install and that updates what you might know if you've seen like a yarn lock file there's a gem file file as well again i think inspiration from things of today so that's a quick overview of the gem file we won't be adding any third-party gems to this app just because we don't need to i don't think but this is where you would if you needed to reference a gem and gems are very useful so i wouldn't be scared to add any to your app they do come with you know you are dependent on them but they aren't something that you should frown away upon if you need something special okay so with our app set up we need to go and add that root path i was just talking about so routes a way to add the root path in this case we'll just say root two and then we need to kind of call out a specific controller in our case since the controller logic is going to be what requests route through so entries index and what that means it's going to go to the entries controller and find that index action and root to that so when we boot up our app anywhere it will go to that file that that path by default now instead of the welcome screen we see so to make that a little more clear if we go to the entries controller it's going to actually root to this action that we saw before and i'll get some what more of the stuff in this file means in a second i just want to kind of show you the scopes of everything else first so we've got our app running you could probably maybe reboot it but i think we're fine to just refresh at this point and it should redirect us back to our root path which is entries right now now we don't have any styles installed i deleted that scaffolds file and that was up by design because i want to add bulma next so if we were to go to overview in bulma i think it's bulma io yeah and start um you could install this like with npm or yarn in our case but i'm gonna actually add it just via the cdn to save us some time and you might be wondering where the where do i add this it's actually going to be in the views folder and then you might have saw this layouts folder and this is what you would call i guess the main main template of your apps so there's one for both the mailer and the application itself you can have multiple layouts depending on what you need and you can establish layouts based on you know wherever you want in your app if you want a specific one but i've seen mostly apps use kind of a standard base layout and then kind of just extend it from there what we'll do for our app is add first that meta tag that came from bulma just copy and paste it over and then we're gonna go and add their version that's a cdn port so right here so this file we'll paste in right there and then we'll have bowman by default now i'll refresh this page and you'll see things kind of just cleaning themselves up which looks pretty good but very naked at this point so that's fine now to get started let's go and make our actual app we have our title of our app that's called food log so in our html file you see it up in our our browser tab there it's called food log next we can add a container class around what's this called this yield statement and this yield is essentially the way where the content of the main app will render so whatever you're going to render basically app wide will be injected here thanks to how ruby and rails work so that will kind of shift things more center in our app and get us ready to roll there um inside each of our views you might notice so in our index view in particular up at the top there's this notice method and the way rails works with controllers is it can actually display a notice when things happen under the hood so after you create a post or an entry in this case this notice will inject this text into that that variable we just actually spotted and i'm mentioning this because this is more of a global thing so i think it fits better within this file instead of with the scaffold treats um as as home here so we'll actually cut this out of this file and i'll paste it in the top under the body section of this file and what i'm going to do is actually kind of do a conditional check if it's actually present so we can do a little bit of ruby within these html files and ruby if you're not familiar with ruby it's fairly simple language to learn but there are a lot of hidden quirks again it's a dynamic language so i would say it takes a lot of time to master but it's quick to pick up so there's a command in ruby called present we could check out if basically there is a notice and then render it so i'll leave that alone i'm going to get rid of the id bulma comes with some classes that we can actually prepend to this and call notification is link and then is light and be sure to round out the div now what's great is there's another one called alert so this is typically what displays if there's an error like say you submit the wrong data in a form we'll present that in this way as well maybe just changing the colors up danger is light so this will be kind of a red to you and this one will be a bluish hue so we'll leave it at that what i want to do is eventually render a header above these bulma comes with some pre-defined header templates so we can actually kind of go that route what's great is within erb files you can render partials and if you're not familiar with with how partials work if you look into our main app right now and go to the new file within the entries folder this is how a partial gets injected into another page so you typically pass this render function and or method within it you pass what you're rendering in this case we're rendering this underscore form file and the underscore basically tells rails that that is a partial we want to render that as a partial into another page and you can even pass variables through so in this case we're passing the variable or entry or the instance of entry through to the the actual form itself so in that case the form again this is all rails specific stuff has all these entry local variables available to it since we passed it through in that way in the new file so right here this actually is the instance that gets passed through and then we're able to use it in this file specifically right here now i'll talk more about this file in a second when we do some cleanup of the html but for now that's just how that would work if you're thinking of parcels all that's to say is i want to render a partial into our application file and i want it to be called header so what i'll actually do is create a new folder in our app that's going to be called shared and then header so we need to create that in our views folder so i'll actually do so and create a shared folder inside that we'll create an underscoreheader.html.erb file and then i could just say my i'll just do like a proof of concept here so my header save that down if we re-render the app at this point you'll see that text appears so that's that's working that's great now what we want to do is actually use some bulma for that so i know there's some kind of prevent template markup will probably reference so maybe i'll go get that now modified it so i'm going to copy and paste most of this over we'll paste it in that partial just to get going with it so then if we render the page here we've got at least the markup it's not dynamic by any means but it is markup and we don't have the icons i'm not going to really use icons i don't think we need them but i'm going to make this one small i think it's a little too big otherwise and then we'll have we can change our logo up in a second but we'll leave things alone probably just remove all of these links for now we just need to remember we're going to do a link to new entry path class button is success so we'll have kind of a blue button now on these helpers you can do them inline like so i'm getting ahead of myself here so you could just say like create new entry in fact i will i'll just do create new entry and show you kind of what's going on it might not work right just because of the spacing so bulma expects a span tag there but let's make this actually is link so it's blue there we go that kind of looks like i showed you in the beginning um but you see that's how it's how it's at the top there that's not exactly how we want it but typically this is how a traditional link to helper works you pass the text of the link there you pass the path of the rails route there in this case we're going to create a new entry so we need new entry path and then the classes you can append to and there's a lot more you can add to that the documentation again is one of your places to figure out all the stuff you can add but under the hood it adds this class with the href of entries slash new that's all convention driven there but let's add that span tag so to actually do that we need to make a block version of this link and to do that you just throw a do block at the end and then remember the end tag here otherwise this will not work now you might think this could work at this point too but this format assumes there's no text based option there so you need to do it here instead and in this case to get the spacing we need for bulma to work we need to just pass a span tag like so and that still doesn't work so that's interesting i think it's because i still need the span tag here actually so span class navbar item okay see that there we go that might be not really necessary let's see if it is remember to remove the do block okay so it's not great okay so that gives us at least a button that does something so we can click that now and it'll actually go to the new path the url up here goes to entry slash new and you'll notice that form we were actually looking at earlier with all those fields it looks like garbage but we'll fix that up here well i'm going to remove these nav elements we don't need those at all so i'm going to actually just kind of remove the footer itself and render that now the title is going to be actually dynamic and i think it's going to be kind of a neat part because we want to actually render it based on the date so the way to do this is using that yield statement we saw before but what's neat is you can pass in custom yields so we could say yield in our case i'll just call this title and that's great you could check if that exists though and that's kind of nice too so we'll say if content for title will render whatever we pass through and i'll show you how this works in a second if it's not quite clear but we can actually throw an else in line here too and just pass in the name of the app instead so food log in this case and i'll actually just remove subtitle i don't think we need that okay so that gives us food log because we didn't really yield to title at all now if we wanted to i'll show you by example how this works in our index path eventually we'll add a date based on our entry itself that's going to basically show the current date so we'll say in our index html file content for title do and another ruby block there we could say food log and i'll just do like a in dash html version and then we could just say like um date time dot now it's going to look funky but we'll fix it and there we go so that gives a timestamp of the current time and date again we'll fix that because it looks bad but we'll notice how it's dynamic so on any index action i could change that here i could render something different on this page it's all relative to whatever you want to throw in that context i forgot to delete this from the show view so we because we have it here if you recall so i'm going to go ahead and just remove those for now so those should only really be on the show and index views so there's other files in this folder the jbuilder ones you can go and assume you can either delete those or keep those but that's just the way rails hooks into another gem and renders json in a very automatic way that we won't really use in this app but you could so if you were to ever want to render entries.json i think you can and my firefox browser will actually display it as json here once we have it that's just kind of a nice to have or if you need it at all so on our traditional app let's go ahead and create an entry just to show something let's create one called uh breakfast calories would be like i don't know 600 whoa 30 20 i'm random numbers here guys so 50 create entry okay here's that notice we created and remember that was added here it's got the link classes and it's light so that actually works quite well for us now it doesn't dynamically go away you need to add some javascript to the app to do that we won't get into that but that's just something to be aware of refresh this page it'll actually go away by itself on this page right here we're actually on the show template so any any route you've seen with the actual id that's going to be the show template and on this template it simply typically just shows the data for that specific record in mention in the database so in our case we just created this one it has these calories the breakdown and whatnot so we can go ahead and go back to our edit page and you see all that data is still present in the form we go back to the show page you'll see that again or back to our index path and you see the the state of things right there so what i want to get into next is kind of just cleaning up these views so it looks a little nicer i'll do that quickly it's spend too much time with this uh by default they scaffold the tables it's not the most useful thing in the world from a designer's perspective but it does seem to work when you need it a scaffold isn't meant to be taken as like the final product anyway so okay so we're going to start on our index view first just because this is the kind of the root path to our app at this point just kind of get rid of any crafts we don't need i'm actually going to remove this link and what i'll add is some bulma markup so we'll have a columns class and i'm using emmit to kind of autocomplete the stuff that's another plugin for vs code if you want to check it out mt6 is centered these classes all come from bulma so if you're wondering where they come from that is where and then right here is the ruby looping mechanism so it's quite simpler than most loops you see elsewhere and in modern javascript you might have a for each loop or something like that where you loop through an array this is kind of the same thing only and entries is kind of a hash or a collection in ruby instead of a typical array or it's an array of hashes i should say so let's get the column is one quarter just want to kind of give these all their own little look and feel um we're going to give a card class next so card actually i'm going to go steal i'll just i'll follow my notes here card so the main card class will be wrapped that way in the card class we'll have a header class card header and that will have the entry meal type and below that we'll have a div card content and within that there's another classical content that's kind of just a generic content class that comes from bulma we'll have each of our kind of entries based on the macros so these won't really have any they're just text at this point so we need to add some formatting so i'm going to do for each of these i'm going to do kind of the same look span class as text weight bold close that off at the end i'm going to end the span but then for each of these we'll end the paragraph tag as well and then after each i'll just say calories not each but grams of protein grams of carbohydrates and then grams of fat okay and then we could kind of add a time stamp too and just do a generic like italic class and i'll say it was logged a nice time helper in rails is one called time ago in words another benefit of a framework you just have these available to you and then these this field that we got created by default so if you recall the timestamps declaration in that migration we added uh way back when this thing here created uh created it's basically created at and updated at field to use so updated out it's useful if you're like doing editorial kind of things and then created that's useful if you just want to know the birth date of some type of file or not file record then we'll do a card footer to round this out so pass that down i'll clean up this formatting okay and each of these are going to have a class of card footer item so i'm going to kind of do the command click cursor thing in vs code and say card footer item and that's i didn't say this before this is how you add html classes to erb based stuff so you'd add a little bit backwards than typical html okay now we can check this out and see how it looks so there's our basic look and feel looks like i might have something wrong with the header class yeah we don't we need an actual class here for card header title there we go so that's our first entry that was what we added in that form and i need like a go here there we go so this is kind of a nice helper like it'll start with minutes it'll start go actually start with seconds minutes days hours etc until it gets to like several days and then it'll say days ago and and whatnot so it's kind of dynamic in that way which is kind of nice but to get this timestamp to actually look like i want we need to kind of add to the framework a bit so what i tend to do is go way back into our configuration part of the app and create a new what's called initializer so all of these files in this app are loaded when the when the actual app boots so we would need to restart the server for this to take effect but what i want to add is a new time format that's kind of just preset ruby has a ton of ways to render time in a certain string format this will basically create that customization for us that we can reference it in the view in a nice handy helper based way so what i'll do is create a new file called time format dot rb and it's going to have a pretty seemingly simple file our contents and we're gonna hook into the time class of ruby itself and for rails we'll pass in formats so that's part of the standard string formats we can pass and hook in and pass one called nice date you can name this whatever you want and this is a symbol in ruby this is a class this is a constant on the class yeah there's a lot to ruby but if you're not sure of it definitely um check the documentation and kind of get familiar there's some other sites like code academy and whatnot that have decent starter guides on ruby itself so this format is what's going to render the actual date format that we want so in this case um we're going to get like the full year the i honestly can't remember so i'll save this down and you'll see what i mean so what we need to do though for this to take effect is go back to this view in our terminal we've got our server running how do you quit it control c on a mac will do that so what i tend to do is hit the up arrow again in the same instance if if i would only ran rails server before and you get that command right back and so i'll run it again and we can go back to our app and hopefully see nothing yet because we didn't use this but let's see if it works so the way we'd access this where i want to check take effect initially is in this app this uh top portion here in this content4 block so what i'll do is actually do dot now and then render to string so that's a method in ruby to render the format to a string and we'll pass that new um time format stamp we created that symbol so in theory this should render right back to where we want it so that's the nice look and feel of that one after which is perfect so that takes care of the index view if we were to add another one we could do launch launch j yeah so 500 i don't know 20 three i'm just random here there we go we go back and then we have two so that's that's how that all works we've got our edit and if you want to delete one you totally could i won't just so we have some stuff to view and to save some time but that's just the way it it's looking right now this is probably bugging you guys that i don't have the right logo so i'll do that quick okay so i did a basic span tag and i actually want to make this a link back to the root path of the site so what you can do and what's handy thanks to rails is just call root path since we have that set now in our routes and then we can pass the the bulma class we need so now bar item and then if i can type a do block and then within that we'll i want to add an svg i'll do that in a second and you can reference the source code i'll paste a link to it in the description i'm going to just pass some bulma stuff here and we'll say food log so that gives us the look of our app at the moment and i need to do a dash there so there we go i wanted to pass the svg into this code i use an app called nucleo and some zondicons i think steve sugar if you've heard of tailwind and that crew he's one of the designers for it so if we say food i think i use this one these are open source so you can use them pretty sparingly if you want to one thing that's i got you here is i just need to remove this little g tag it kind of adds a color to it i actually want to set the fill to white there we go and close this app refresh there we go we've got our logo not perfect very quick and and and yeah but it works okay last thing to do is take care of these form views they don't look very good so let's make sure they do at least in terms of bulma's setup what i want to do for each edit if you notice edit and new share the same form partial that's by design which is handy so what's great is we can just kind of copy some of the stuff over and already be in good shape so we could say columns dot is centered martin top six just wrap this all up and then i did one column i kind of wanted this to shift to the center and a smaller width so i just did column is one third so we'll shift that over and then our h1 for this page we'll have class is size two has text weight bold and margin bottom three and then we could close that tag we'll have editing entry we'll render our form i'm actually going to remove these links i don't think we need those so if we go to our edit view now we get this look and feel our form still needs some love we'll get that now so thanks to bulma this is almost already done one thing we need to do is for the errors that would render if we were to uh render any we need to kind of account for those so instead of this id eric's explanation i'm going to add a class message is danger and then we'll have a message header that's going to wrap around this h2 or it will be a p tag actually do div and that's good if you're looking at this method pluralize basically it takes a count so if there are any errors it counts what's in that array of errors and outputs a pluralized version of this word so if there's only one error it'll say one error if there's only like four errors it'll save four errors it's kind of an inside scoop there and then we could do make sure this looks pretty good fix the indentation a bit okay so that's if we have errors i'll show you how that looks in a second when i talk about validating these fields for each of the labels we'll have a class of label oops we need to do that we can actually just kind of do a command d select all these go to the end come back label down a line these will have a class of input field is actually already one of the classes we need for boneless so that's already looking good and then finally on our bottom submit button this will be a button that actually outputs we'll need a class button is success now you notice there's no text to say what this button actually reads as that's kind of a conventional as well thanks to rails so based on the path you're at uh new or edit in this case it'll say a certain thing um so we'll fix that up in a second i'm going to copy pretty much the same stuff over to the new file and i'll show you the difference here instead of editing a tree we'll just say new entry and it's all the same so we'll just paste that in and save it close some of these files up and i believe we should be good shape so now we have this look and feel thanks to bulma this was us editing in entry if we update we'll go back to the show view and then back to our index view what's left to do is essentially the show view we've got a new entry form see it's using the same form partial so everything kind of looks the same except for this headline so if we go back to our app and do edit on this one we'll see editing instead and then the data that propagates to each field thanks to the database that's that's loading that stuff up now if we were to go to the show view it looks like this so let's tackle that now entries show this is what you're getting with the scaffold it's not that pretty but we can make it that so content4 we'll do that again here this will allow us to do like a more dynamic naming convention for what entry we've added so in our case we could say like entry meal type and then we could display like an in-dash kind of like we did before and then our our date time stamp again so date time now to string nice date there we go so this was breakfast on august 27 2020 if we go back to here it's food log august 27 2020. this is all going to update based on the date that this was authored so that's pretty dynamic and useful okay so continuing on i'm going to do more of the bulma stuff here so we'll just do columns margin top six that is centered wrap that all let me get rid of these p tags and these strong tags okay and meal type will be there we can do i think there's a panel component column is one third again we're going to shift this to the center and kind of a smaller looking unit nudge this over save that down meal type will have a panel it's actually going to be a nav so we can say nav dot panel dot is link and within that we'll have our kind of look panel heading will be oops or meal type you don't even need these labels per se um calories will be these will be panel blocks so we'll just kind of copy this down oops i'm going to keep the calories there actually okay so i'll just kind of follow suit with these two or three come on go okay so that's that we still need that like bottom portion of this to do some utility stuff around it so i'll do another columns and then is mobile to kind of account for that it's not i wouldn't call this app very responsive friendly but it's got bulma so you wouldn't be far off to go ahead and go back through and make it that way if you wanted to pull it down i'll be sharing a github link you can download this from this button is gray move that back we don't want back here instead we can do a delete so a delete button is going to reference the same entry path so in this case we could say entry path and then pass in which one so we've got that instance variable of that entry since this is the show view and how that works is on the controller layer if you go back to the controller layer there's this set entry method at the very bottom of the file and there's this concept of parameters where based on the request there's an id in the parameter now if we were to go to this show view i'll show you what a parameter looks like which you have available to you in any instance of the app which is called params when you echo that out you get this little bit of data about what's going on with the params at this stage so in our case we're on the controller entries as we just we're showing and that action is show so in this case we're on the show view and the id is what we're kind of paying attention to here so in this case it's one now if you go back to that controller file you might notice there's an id symbol here and that's what we're actually going to find based on what's in our database so to find that you'd pass the class of the entry itself so in this case this is calling the model class which is located here the one we were talking about way earlier and it's finding that that entry based on that id and that parameter session so you're able to kind of pluck that stuff out of the database to get data on it in this way now how is this going to coincide with this show route or action right here is another handy way that rails does things kind of in a more dry approach so don't repeat yourself is the is a kind of common programming lingo and in a way this is a kind of a callback so if you think of something that happens before something else this is what that is so here we're calling that method way down here and finding that entry based on its id and then we're using it automatically in these other actions so we're only in this case only the show edit update and destroy actions so we don't even have to you if you didn't have this here you would have to define this method basically this line here otherwise now that gets repetitive because you're ending up needing to do it on edit on uh show on update and destroy to find that id so in this way this boils down to a one-liner and then a single method to kind of call it on each of those actions so i hope that makes sense it's probably a little fuzzy but if if not if it is i think just over time you understand it a little bit more now we want to delete this path and that's where we're calling that that entry we've found based on that method in the controller so it's important to know that this is where that's coming from so in in this case this will have that id of one but we don't need to reference one anywhere which is great so we could just say method in this case we're going to do a delete http requests and call in that route since it's delete request it's going to point to this destroy method now rails has a handy destroy method that you just chain to the object and it'll handle it that way so it's just basically going to the database and deleting that record from it then this is kind of the magic of the framework so in this case we need to pass a method because we're deleting it and then we can just do with with some of the data attributes rails ships with this library called rails uijs and that's kind of installed via our javascript so if you go into javascript packs application.js there's this ujs library and that's just kind of some built-ins that come with rails that are helpful in the case of when you delete a record you might want to do a confirmation window kind of confirming that case and this is doing exactly that so we can call this confirm and then we'll just say are you sure and then pass another class at the end that does the button and then is gray and i'll show you in the html how this looks so you get an idea we'll do another column here and we'll come back to this portion and add uh something coming up that i want to do to show you kind of the full index of entries instead of just the view of the current one so what i want to do first is remove this line save that down so we don't spit that out now under the hood if you see this link it's the a a a tag it's got our classes and then this data confirm message that's just the way to pass a message through through to the browser so on this dialog notice it's when i click delete it goes and does this that's that ujs library i was talking about that's a little bit of javascript making that work for us and then edit goes right back to our form just like it would okay so with that done we've got our views stylized and looking pretty good everything's kind of working swimmingly as shown in the beginning of the app there was this actual index of all of your dates and entries so let's do that next and i'll show you how that works so i'll do a generation on the command line to generate the next part that's going to kind of save us some time so i'll open up a new tab i've got one open here i'll just clear that off so video rails generate controller i'll just create a static controller typically a controller is plural in the naming conventions so in our case this one's going to be static it's kind of more geared towards just generic stuff um you could call it anything else like archives or something like that um just to show the index of everything but that's what we're going to focus on here i'm going to pass an all name to this and this will essentially be in fact i'm going to call it archive just so this might be a little more clear [Music] and then i'll pass this name all so this is method on that that controller the controller name is going to be called archives controller and then on it we're going to have on within the class on that controller we're going to have an all action all will correspond to kind of everything that we've input so far and traditionally you could do that it's not the most what they call restful way so instead we might do something like index and that gives us an index of all of our archives so i think that makes a little more sense and that's kind of the convention you would pull die by with rails when you name things especially there's a lot of conventions to understand and kind of get in the habit of using but it's once you do it kind of makes more sense and it's easier to spot bugs and find errors and solutions to errors when you do some googling like i have so let's go ahead and run this it's going to generate our views and our helpers all that stuff you kind of saw on the scaffold but a little less because we didn't generate a model with this we didn't generate any of the kind of data layer side of it because we don't really need it with this part of the app so let's go and create the routes i'll show you how that looks now we've got to find it this was added thanks to that generator so that's already kind of doing what we need we don't really need anything more than this if you were to extend archive to be a little bit you know more verbose you could do that but in this case we should be fine actually what i want to do is change this to archives so i'll show you a nice nice to know thing so if i did this generator but you might want to undo what you did so instead of generate so you could say rails delete or d for short controller archive and it will go back through and kind of find and replace and remove that stuff so what i actually wanted to write is generate controller pluralize this one so archives and then index there you go so notice it's archives now that's just kind of a tradition or convention i would say to rails especially with actual full resources so notice entries itself was plural because we scaffold that whole thing but in this case we just need the basics so in this controller i'm going to actually have we're going to call our entries as well so i'll just say entries and what i want to do is get entry and then we're going to group by a specific we'll get entry all first and this is basically going to pull all the entries back and display them in kind of just the the way they were added to the database so and basically by created that date and i'll get into more maybe how that works in a second where you can query here for specific things because you can you can do things like ordering or you can do like where some attribute is true like featured true something like that to allow you to kind of bring back the data you want instead of just all of it you know so for now we're going to leave that alone we did create a view with this so let's go go get that rolling for now so it'll be in the archives and when you generate a new view this is what's inside it's nothing special but we get that for free i'm going to start getting the html part of this setup so centered kind of do our usual thing so column is half and we're going to loop through all the entries here each do entry and i'll for now i'll just do like entry meal type and just call that good and go check out the path it would be on so maybe we can add a button to view all of the entries on the index i'll do that now this allows us to link over to that that specific page instead so at the bottom of our entries index view i'll do this right below everything so we'll just say columns is centered and then margin top six then we'll say link to view all entries i will say archives index path and that's all named based on their routing so if you're calling our routes we've got arc i need to remove that one but archives index i think we still have some of the old stuff too archives controller archives yeah so archives index will be a get attribute there so we get this naming convention as a result so we can just pass class button is link is outlined is centered see if that works in our view there we go so view all entries should take us to our our entries but we unfortunately don't have this working so entries needs to be souped up a little bit so archives controller entry.oh interesting that that's not working oh because i can't spell entries there we go so we've got both of those entries here that's the same ones that are right here but what i want to do is basically group these by a specific date so each entry i want to basically display each one corresponding to its date and not just each entry so to do that you can actually use a grouping mechanism from rails that's a nice thing to have in the sense of getting content to be grouped based on the looping mechanism so in that case we're going to do a group by and then what i'll pass is in day here and this kind of goes through each of the records and maps through the day which will be a new method i'm going to create on the entry file which basically hooks into another part of the column on the database so self self is part of ruby basically just calling itself so you could say enter here and do the same stuff or you could say self and it will reference the class so we'll say create it at part ruby again it's another time format you can pass we'll do b e comma year so this is how we're going to kind of group it by that date stamp and we'll get things going here right now it will error out because we need to loop through it a special way to make this work and i'll show you how that works right now so if we go back to this entries index we got injuries at each but this is actually kind of a sub array of data so we actually need to pass that day entry now and then we can call entries specifically and this allows us to go one step further in this loop so what we can do is first i'll create a h3 class with a size four has text weight bold margin bottom four has text centered so in here we'll do entries for day since we've got that available to us in this loop now that comes right here and then we can get the sum of the day so in this case i'm going to do first i'm going to do the loop below so i'm going to say entries dot each do and again see there's a first start of the loop and we actually need to end it so we aren't oh we did end it so we need to loop through this entries now since we've got it grouped this allows us to do that so we could say entry do like a sub loop and if you want to think of it that way and then we'll do one big link to that's going to wrap each entry do then we'll just present a card element just a basic break tag and just kind of just basic text so entry dot calories we're going to do it all in line so it's comma separated all right so that gives us what that would look like at this point i'll show you looks like i need to do [Music] i have spelling always off on the spelling there we go so see how it's grouped and that's that's by design that's what i wanted so we've got this one single date with this queried of sub entries for that specific date so we've got that all ready to roll i'm gonna remove these spaces real quick so then we get kind of just a high level of what's going on each of these linked to their own perspective individual records so in this case we go to breakfast and this one goes to lunch so that's how that works what i want to add still are some stats for the whole day though so what we can do above is present a nav class or nav element and it's called level for a class and let's say is mobile i think i stole this straight from bulma but we'll just copy it for here level item has text centered and then we did quite a few of these so i'll just get the scaffold of it written and then we'll go from there so div first will be calories and this is what we're going to do we're going to go through all the entries dot pluck basically pulls out the singular database column and then gets the sum of them with ruby here so for each of these entries specifically we'll just kind of do a little bit of operation to summarize each so that's a super handy thing and another reason i like you know ruby and stuff it's just so simplified like this breakdown for the day is this stuff right here this adds those two things so we've got 23 and 32 adds to 55 and i could probably put grams for these so protein grams uh in the states it's grams you might use something else where you're at there we go and like calorie what is it cacao something like that if you want to go that route i might leave that off but that's generally it so if we posted again for august 28th we've got another day of this there'll be this long index of this stuff eventually you could add stuff like pagination to the mix the longer this goes on and how more consistent you are with documenting your food log so that's the face of the app that's the the data layer what i want to do real quick is talk about validation in the app and right now if you were to submit the form on any creation of a new entry it would submit without anything and that's not what we want so we want some validations there and what's great is you could do such that in your model you can display those specific validations based on what you want to pass so in our case we want to validate that they're actually present so a way to do that and there's a ton of other validations i just want to show you how it works right now we want to make sure there are calories proteins carbohydrates fats and a meal type and at the very end we could say presents if i can type presents true so this essentially says these need to be input otherwise this form will not submit so if we go back try to hit create entry again we'll see that error status come back so in this these fields come back through based on the name of the field and then just the conventions of rails so we get this back and it's super helpful in that way now you could do a ton more validations based on like what kind of entry it is say it needs to be a number it needs to be unique needs to be capitalized or some sort of text formatted way there's a lot to check off on that list so go ahead and check out the documentation for that one extra thing we could do is for make sure this is actually for today so this is just displaying to the the date right now and what i want to do is only get the entries that are created today so if i were to create one tomorrow it would show up here too and then given the current date that's not exactly what we want so on the index of our controller today we've got entries.controller we're just displaying every entry and that doesn't really make sense when you're logging in or when you pull up this app you're adding your calories you probably don't want to see something from two weeks ago instead you want to see what you're focused on which is today so what we can do is do a where query we'll do a created app and then we'll do a pass and basically greater than equal to what and then we can pass what that what is and today would be the case so we could see date dot today and this won't really change but if we were to add entry i don't know and update it to yesterday so maybe we could do a little bit of that so if we say rails console and this is a great way to play with the data in your app we could say entry give it a local variable and then we could call that same class in our app so entry equals entry i'm going to just say entry.last it's a kind of a ruby convention to say the last one that was created and we're going to pull that back and it'll pull back one so if we say entry we get some data about that entry as you can see here it's got some of the data based on what's in our database so if you say entry dot created at equals um let's see how do we do this date dot yesterday i think that might work so we could assign it yesterday's date and we saved it by saying entry dot save you can command or control d to get out of that refresh your app you should only see today's stuff so that because that yesterday entry was for august uh 26th in this case so what we can do i need to add some margin to that let's see margin top i'll put a little bit of margin on the entry header just so it's kind of not bumping up but that's not perfect but not terrible either so we've got entries for both days now that we made that change which is pretty useful finally i want to talk about some testing in rails and that's specifically a pretty big convention to boo to do more tests with the rails framework because ruby is a little bit loosely typed pretty dynamic language and is something that you want to test to make sure a lot of things are what you might expect so under the hood there could be a whole new video about tests in general i want to walk through just the scaffolded stuff since we've added that in particular there's these things called fixtures which kind of are a way to mock your data in your database so it's based on yaml files and this is kind of a little more advanced so if you want to stop here that's fine you've probably gotten the most of the framework at least the the basics of creating uh resources and doing things um with rails but this is kind of more or less how you could do the testing side of it which is pretty important so we'll say lunch here and you could put meal type breakfast think of this as just dummy data we can work with and under the hood uh rails ships with mini tests it's a library for testing in ruby actually i think it might ship with ruby if i'm not mistaken but um basically it's just a way to confirm your suspicions of your code and do a lot on to it that's just pre-baked into the framework a lot of people tend to use one a library called r-spec it's just kind of a more enhanced version of many tests they follow the same ideals but they are different in terms of syntax and everything else so up to you if you want to kind of go deep on that end what i want to do first is just talk about controller tests i'm going to go through these pretty fast just so we get this video not too crazily long but i want to respect your time anyway to set up a new entry we need an instance of like a an actual object we'll use in a database so to run tests in rails there's a whole separate database in your app typically to do such as that if you were to check out your environments there's there's three different environments by default one's test and there's ways to configure it if you want to do it independently we are working in both development and test at this point production is a different one that you would of course do when you push a web app live like this so what we want to do first is run this entries controller test and see what barks basically you want to make sure the test fails first when you run a rails test or a ruby test so to run a test you would actually pass rails test and then pass the actual file path so in our case it's going to be test controllers and then entries controller tests let's see what comes back and right now we can't load the file because i think it passed the wrong path excuse me it's rails test and then test controllers and choose control tests and then you'll see this boot up and run stuff don't worry about this uh readout here this is all just kind of ruby depreciated code stuff you don't really need to worry about but it is it's kind of annoying i know so right now everything's green because we didn't really modify anything to do with our controllers but when i what i want to point out is just if you go to the entries index for instance you could run this test single in a single fashion so if you do test pass the line number that you see so in this case we've got eight it'll just run that specific test i types wrong again so it'll just run that specific test you notice it's green here so typically you want a test to fail uh to to begin with so um in this case this is already set up i just want to walk through it just to show you how this could kind of work in your own app if you create a new resource without scaffolding it this is kind of the the rails scaffold way so don't take this way as like the only way but just a way to kind of follow in a pattern so you basically in a controller test you're testing the responses so in our case we're getting the entries url which is our root path in this case and we're asserting that that response is a successful one the same is true for the new path and then when you create an entry want to kind of confirm that we go to the last entry that was created and passing in uh post request which is basically just asserting that it is a post request or a form is submitted we're going to this specific url with these parameters from the form so in this case it's what fields are being filled out and then within this param of entry so that i'm i'm going fast i know it's a little probably advanced for a crash course but i just want to kind of cover tests because it's commonly overlooked in a lot of crash course stuff or beginner stuff even though it shouldn't be so edits the same way we get an entry url we assert success updates quite similar to create create only we just assert it goes to a different url um and then destroy is kind of the same we just get the count of the model itself and make sure it is subtracted by one so all these assert difference and and everything kind of come with many tests and and parts of rails under the hood we also have model tests so entry tests there's nothing here at this point but we could add some so let's do that real quick let's do a test and we'll call it is valid with valid attributes this is basically saying we can create a new record and it is valid and i need the do block so what this would look like is we can create a new instance of entry in this case so we could say like a local variable entry equals entry dot new pass in our own parameters so meal type just whatever these are these need to be numbers since that's what we proteins 20 fats 10 calories 400 and then we could just assert that it was saved so entry not saved so it basically can be saved now a test you actually want it to fail first so if we missed one of these fields what happens so i'll try to run this now it'll be a new pathful type so rails test test models entries test i think it's just entry test excuse me dot rb and to save some time we could just pass the line four it doesn't try to run the whole file even though we'll get there so it is failing which we can see in red so it's expected to be false or expected false to be truth if we add that back does it work it does so it's green so that's a quick way to test that it is at least valid now because we've added those validations typically you would add that after the fact so tests typically tell you what to go next if you're following test driven development so i did things backwards i did the validations first and now we're writing tests for that now you might find that's fine and that's useful some would argue that's not the way to do it but to me it's like preference you know whatever preference you should say use that so we want to test each field now so we should say should not save entry without calories do end we're going to basically do this for each field just to you know validate so we could say carbohydrates these are a little bit redundant because of this but in this case we could say you know if you've missed one it should still pass the test i just want to show you what kind of tests look like in this case so proteins and fats okay so now we've got each now i just need to assert that they're each that way all you need to do is just go in entry dot save assert not in this case but we want to take out the calories from this equation then we could run that make sure we could say first yeah we could just run that first and say nine cool that one casts we can also kind of make sure it doesn't work so it still works so these are in all seriousness these are redundant so i'm actually going to remove those because if this doesn't save it's valid in this way so that's a quick run through of model tests let's go and work on a system test next so a system test is kind of doing a little bit of integration with a library called capybara and it's a way that kind of uses a chrome based engine to actually fire up your browser kick off some tests run stuff through the tests and then just verify it works so it's it's quite wild when you first see it but it's pretty neat and i wanted to make sure this video actually has that so at this point we we have this test that visiting the index path i know it will fail because this isn't what is on the page so we can run this test and just see what the browser kind of do what it does just to give you an idea so test test system slash entries test dot rb it's going to boot up a browser do some craziness looking for that string but it's not gonna find well it ran the whole file so excuse me i should have ran just the line eight let's focus there so it's kind of stalling because it's like well where is it so i can't find that actual text class so in our case it'll be food log and then an end dash and then we need to pass that timestamp we created so we can run that again hopefully it'll pass yep green so how quick it is when it finds that is a good indicator that it did pass now we can run the next line would be line 13 so instead of 8 we'll pass 13 down and this should i believe fail yeah unable to find link or button new entry because we didn't have it there so if we go to uh creating a new entry we need to visit the the index url and find that entry now it's up here actually but notice it's not saying new entry so instead if we change that to create new entry and i believe it's lower case case matters in this case we'll run that again it can create that test and find link back so we don't have the backlink because we actually removed it so i'm actually going to remove that entirely and run that once more green cool so that worked we can go down the line updating an entry so what was that line 27 so again it's looking for that back link we removed it from there as well we can actually just kind of get rid of that run it again green and then finally 41. i'm going extremely fast here typically tests are kind of going to take almost as long as coding actual feature so it's it's something you need to kind of think uh hard on because you want to actually identify the flow you're creating and making a user go through so in our case we're visiting a path we're clicking on something we're filling in something else these all correspond to a label name or the name of the field and then we're passing in the actual you know item of question and then here we're going to like edit entry we're going to match the first edit button and then go about our business there too so all these tests are useful in that case because you can kind of almost go through the flow automatically and validate that it's working and acting as it should typically you want to almost write this first and then go build your feature so you can make sure you're on the right path but sometimes at least in my perspective i'm more of a designer first i kind of like to get the design hashed out and then come back and kind of clean things up okay so that's system tests um there's there's a lot more we could do so like maybe for archives we could just do rails generate system tests archives so you can generate a test from the command line in our case we're going to do that in this way and we could just do some quick and easy wins here maybe um we're going to do that setup block do again initialize entry we probably don't really need to do this but there's only going to be one test here and we'll just say breakfast and again this is just basically pulling in that dummy data from our fixtures files so it all points to this it's kind of just a convention so it looks like magic but that's that's what's going on behind the scenes we're pulling in this that's named here to get these values as test data to use and the setup block allows you to do it for any test written below so you have that instance variable available to you so you don't have to type a new instance every time so we'll say visiting the archives index we just want to like validate there's some stuff on the page so we'll say visit archives index url we need to use urls and tests instead of paths we're going to cert selector h1 is going to have a text of food log and then assert selector h3 we'll have text of entries for entry dot day if you recall day is what we added to our entry model so entry model it's this method here we're calling which is going to output that time stamp we were after and then we could say finally assert just to verify this stuff on the page entry dot meal type let's run that test we just need to do a little bit of naming swaps here so archives test.rb we could run the whole suite uh looks like i did it wrong looks like i need a do block here forgot that run that again so we've got an error archives because they can't spell so that's what tests are for so archives index url try this again and it's green so cool so we could do a controller test for this as well we've got the index response is already kind of set here this is this should technically work if we just do rails test now let's see if we get a full suite that's green and it looks like it is so again you don't need to worry about this ruby uh output here it's just part of depreciation warnings with newer versions of ruby coming out so up until now we've covered a lot of topics and relative to ruby on rails such a vast framework there's no way i can cover every little bit in this video but there is a ton under the hood where you could extend the app or harness new features and other data right now we only have one model and commonly in apps there's multiple models and typically they're associated so there's this concept it's called active record associations and it's a way models can talk together or share data right now we have one class that's called entry we could add another one that's maybe called the meal type for instance that could be an actual entire model of itself or maybe a category model you know so let's try maybe just creating one just for grins right now just create the category model or generate okay and we'll do the same cleanup because it's just gonna conflict with our other styles otherwise so we'll delete that and we have that whole structure now but they aren't associated per se so a category and an entry are now two models that can connect if we want them to so in my case i want to belong to a category so we can say belongs to category and then a category is going to have many entries so we could say has many entries now for this to work and notice it's plural that's a convention and then belongs to is singular for this to work we need some id to use to know how this can work so an entry is going to essentially need a category id that it saves to the database so what we can do is kind of go through the mix running that migration now we have category let's just say um i don't even know what this would be like um weight loss great okay now we got categories great now here's our food log if we go to our entries controller nothing's really changed but we need to add that we've got that association set up in our model there but our database still needs that kind of construct and the way you can do that is to add an id attribute to the entries table so if we refresh the schema if we j we just say railsdb migrate again it should spit out the new schema structure that we were expecting now we see this categories table which means there is a new table in the database but it doesn't have any connection to entries yet so we can say essentially a one-off migration in this case so we can say rails generate migration we're going to add entry or category id we'll just say category reference to entries and then we could say category references if we've run this migration should create a new file for us that's actually kind of already made up so based on the way we name that method right here it's kind of getting cues of what it should do under the hood and that's very convention driven again in rails there's some bit of magic going on under the hood which some people love some people hate so what this does is adding a reference to the entries table and we're pointing it at a category specifically and then we're setting null to false so it can't be null and then a foreign key to true just to kind of give it a another root in the database i'm gonna go and change this i'm gonna just remove the foreign key and null and just run this again there we go so now we can have a category referencing an entry so entry will have a category id specifically so notice the naming convention here so it wouldn't be an id because this was already going to have an id attribute so instead it takes the name of this table in its singular form and adds it with an underscore id here so that way we can query for that specific id so you see all these conventions coming together and kind of doing their thing it takes a while to understand and get this right so don't fear if it's kind of confusing or you know just a lot to take in but it's just kind of one of those things that once you get it's just a pattern to pull to so we could here for instance go and find we can create some new categories i don't know we've got weight loss let's just create a couple so categories new i'm going to this directly because we don't have any views set up so we could say build muscle just different maybe paths you want to go down okay so if we go back we've got our two categories here kind of might save time and not style these just so you get the gist here but if we go to our form now and our entries give it a new field the form label uh let's say category class label and we can do like a select field so form not select we could get all the categories and there's some kind of weird syntax with selects but if we just get i think it's i might need to refer to bulma's docs but if we do that i think it should render the way we want i'm gonna put this at the end actually let's see if this works it might bark at us so we've got category we don't have everything spitting out just yet let's go to entries controller we need to pass in category id so adding a category id to the mix we need to pass the form select value and get it to display all the categories we're going to loop through with this all that collect and then kind of pass in for the parameters the title itself and then the id as the actual output so if we look at the source we can see entry category id and then the category itself and the options will be the values or the ids of those categories this is a little advanced and i understand it kind of is confusing but this is the way to kind of associate that on the front end so a user can can make their own selection of what category it belongs to um real quick i'm going to see what bulma has to say about selects and we can go from there components elements forms select div class select okay so it needs a div around it let's just say select there we go i can remove this i thought i needed this part instead we'll clean that up close that and then we have bulma's version of select so there we go we got weight loss for that one now right now this won't technically save because we need to actually permit it and part of the permission process actually happens way back down here in the controller i actually added this recently but we need to permit this new parameter on the front end to allow it to come through the back end so when a form is submitted we actually pass these entry params in this case and it's another convention so it'll be whatever model you have underscore params if you generate the controller like i did it'll be passed when you create the new entry and then saved if it's valid now we have permit those fields right there and then the category id we can go and validate that it has a category as well we could just go to the model real quick entries or my entry and you can just say category id like so and then we could try this again so like a food ty or meal type would maybe be dinner no 1200 calories big meal um 20 10 maybe more than that and maybe since it's a big meal we'll build muscle let's see if this works so that saved if you want to check what happened in the logs it might give you an idea that we've got these parameters coming through notice the category id is 2. this is a good way to kind of just debug your work is to look when you're running your localhost server you can see the stuff as forms persist and stuff that gets passed through so in this case our stuff was updated because we permitted that stuff in the in the controller layer so if that's a little fuzzy basically any field you add to your form you want to actually append it here as a symbol a ruby symbol otherwise rails will reject it and not let it pass through so all that's to say if we go back to our index path and and actually output the category we can do so so in this case we could say meal type um i don't know we'll just do like entry dot category dot title and let's see what happens on the home page looks like that's not going to work i know i called it title no class okay so if enter category title we could just say if entry category so sometimes you need to check that these things exist let's just say present there we go so the one has it one didn't that's why we're getting an error so let me um let's do something like that so something like that i don't know if this would be a use case you'd use but it's just an idea of what you could do if you wanted to add this but yeah that's just a general idea of associations so now we have categories available to us if we wanted to go to edit this one we could now add a maybe weight loss to it so now we can go back to the food log we've got weight loss we've got build muscle here and everything's square so with if statements here you can actually do them after the fact ruby lets you do that you could do it surrounding this block a lot of different ways ruby also available has available unless which is pretty neat it's the inversion of if so if you think about that it's kind of nice so we'll leave that alone for now maybe on the show view i'll display the category too just to keep it going so entry dot category that title should subsplay if we go to check one out uh where's it at entry category title oh it's up here so excuse me there i'll probably put that maybe here same kind of look as before so this might bark if we go to this one no we do we have it there so that's great so now any new entry is going to validate that that exists so if we create a new one we've got uh those things and set up category by default it's going to have a selection because one's already selected so that's good so the validation is kind of meaningless in a way but it's just something to think about so that kind of rounds out the validation or the uh relationships so this can extend pretty deep you can have complex relationships between multiple things you can have like reusable relationships so maybe like think of a blog post and comments or something of that nature where you might have comments on other things than blog posts so maybe it's you know a form or whatever that you can actually use interchangeably throughout the app so the sky is the limit that wraps up our app guys i hope you enjoyed this i know it was long is quite a journey but that's the the basis of running a rails app building a rails app and using testing driven development um building a full crud app and and doing some dynamic stuff in terms of rendering and querying editing fields etc hopefully you enjoy this you learn a lot thanks again to traversal media for this opportunity and being an awesome channel to learn from myself i learned a ton of javascript from the channel and i'm really excited to see more that comes out especially with the guest authors and whatnot happening now too so if you enjoyed this again check out my channel it's web crunch and my website is webdashcrunch.com this code will be in the description below i'll share it with you and if you have any questions feel free to get at me on twitter or my website or the channel itself alright guys thanks so much for tuning in take care
Info
Channel: Traversy Media
Views: 92,690
Rating: 4.920104 out of 5
Keywords: ruby on rails, rails, ruby, ruby on rails tutorial
Id: B3Fbujmgo60
Channel Id: undefined
Length: 125min 5sec (7505 seconds)
Published: Sun Sep 20 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.