Let's build a CRUD app with Ruby on Rails and React.js - Part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so today we're gonna be making a crud app with Ruby on Rails and react and the app that we're going to be making is an airline reviews app as you can see in front of me we have this basic example of the app that we're going to be making so if we look here we can see we have this list of different Airlines and each one has this star rating score which is based off reviews that belong to each airline so if we jump into for example United Airlines here we can see we go to a dedicated page for that airline and we have this list of reviews on the left as well as an overall average score and the ability to add a new review here on the right if we jump back we can see for example over here we have an airline that doesn't have any reviews so we can actually take a look at this let's say I add a new review here so let's say we add a good review I'm just gonna give it a title of great time we'll say really enjoyed this flight and we'll give that five stars so we add a review and so basically you can see that in real time that reviews getting added over on the left as well as an overall average score for that airline so we can actually can come back over here and give it a bad review so let's say terrible experience we can say I didn't like the snacks let's say and we'll get that one star and let's add that review as well and I can see we've added that review over on the left as well and that's actually adjusted the overall average score for that airline and now if we jump back over to the main index view you can see the updated average score for the airline there so that's the basic idea it's just a simple crud app it's gonna have airlines and reviews so we're going to be using Ruby on Rails we're gonna use react we're going to use web Packer and some other interesting technologies as well so let's get started so first things first let's go ahead and create a brand new rails app so we can do this for the command line by doing rails new and then app name we're app name is it the name of the app that you want to create so in my case I'm gonna just call this open flights and then we're gonna add a couple of additional things here so what I want to add is I want to do - - web pack equals react and that'll set us up by default to use web Packer and said with react and you can also add batch database equals PostgreSQL and that'll just set us up so that our default database for the app is going to be PostgreSQL and you can add anything else you want for example you can do dash t to remove the default testing if you want to add something like r-spec but this is what our basic commands gonna look like to create our new rails app so I'm going to go ahead and just hit enter and run that so now once that finishes running let's go ahead and see the into the new map that we just created so let's go ahead and create our new database so we can get rails DB create and then let's go ahead and just open this up in a code editor so I'm going to open this in vs code and I'm gonna start by building out everything we need on the rail side first and then after that we can move into the react side of things but the first thing that I want to do is I want to set up the models that we need for our app so the initial models for our app are going to be pretty simple we're going to have airlines and then our airlines are going to have many reviews so we want to do is create an airline model and a review model initially so for our airline model when I think about the attributes that I want to add for that we want to have a name for each airline we also are probably gonna want to have like an image URL that we can use for each Airlines logo and then I also want to add a unique slug that we can use as an identifier for each airline and then for our review model I'm gonna have a title or a headline for each review we also want a description or a body and then I also want to add a score and the scoring system that I'm going to use is going to be a star rating system that ranges from one to five where one is going to be the worst and five is going to be the best and then we also want to add an airline ID for the parent airline that each review belongs to so what we can do is jump back into our command line and we can just use a rails generator to create our new models so we new rails G model to use a generator to create a new model and what I want to do is first want to create my airline model so do rails G model airline and then I want to go ahead and create all the attributes here that I want to add to this model so we want to create a name for each airline and that's gonna be a string we also want to create an image URL for each airline which is also going to be a string and then for each airline I want to create a unique slug which is also going to be a string so we can go ahead and just hit enter and that'll generate a new airline model for us and then I want to go ahead and do the same thing for our review model somebody rails G model again but this time we're going to do review and for this only give it a title just gonna be a string I want to give it a description which would be a string or maybe a type of text I'm just gonna leave that as a string for now and then we also wanna give it a score I sell a range from one to five and then we also want to clarify the relationship and in this case reviews are going to belong to Airlines so what we can do is actually do airline and then we can do Poland belongs to and by doing that we can basically just establish the belongs to relationship between our reviews in our airline and we'll see in a second is this will also handle setting up the foreign key on the table and create an index for us on the airline ID for reviews so let's go ahead and hit enter and run that okay so now if we jump over into our app if we go into models what we'll see now is that we have this new airline model and we can see we also have a review model and because we specified that belongs to relationship in our generator you can see it actually already added belongs to airline here for us within our review model which is pretty cool so now if we jump into DB migrate we can see that we actually created two new migrations as well so rails uses active record which tightly couples our models with the structure of our database so when we ran that generator we basically created models with attributes and we simultaneously created two migrations to create new tables for our database with those same attributes as fields so you can see in this example we created a migration to create a new table for airlines in our database and you can see that all the attributes we specified from the command line are here as fields sort of name with the type string and we have image URL with the type string and then we have our slug with the type of string if we jump into the other file we can see that we also created a table for reviews and this also has like all the fields that we created in our generator so we have our title as a string we have our description as a string you can see we specified score as an integer and then you can actually see that this set up that belongs to relationship so that takes care of having to add the airline ID as the foreign key for this table and it'll actually create an index for us as well so if that all looks good then what we can do is jump back over into our terminal you just run rails DB my grave and what we'll see is that that will create a new schema file for us in a second and you can see that just added this schema file and now if we jump over here we can see we have these two new tables created in our database so we have our Airlines table and we have our reviews table and you can actually take a look and see that it's added the airline ID for us and then it's added in index as well so then one more quick thing we just need to do so because we specified that relationship we saw that review already has belongs to airline in it but we don't actually have that set up in our airline model yet so to handle the has many part of the relationship we just have to add as many reviews here in our airline model so inside of our Li model I want to add a couple additional things here so I want to add a way that when we create a new airline we take the name of that airline and we basically solidify it and then set that as the slug value before we then save that new airline to our database so what we can do is basically create a slug áfive method and what I want to do is basically just set this up so that it takes the Airlines name and convert it into a URL safe slug and then sets it as the slug value so we can basically do is just something like self-thought slug equals and then we can take the name of the airline and just call parameterize on it and what that should do is basically create a URL safe version of the name so we can jump over here and actually test that out really quick so if we jump into our rails console let's say that we have a name of an airline like United Airlines I unless we call parameterize on that you can see it basically will convert that from this structure where it has for example capital letters and spaces and it'll actually hyphenate the spaces and lowercase everything so what I'm gonna do is I'm gonna set this up with a or create callback as we do before create slug of five and so what that will do is basically set the slug before our line before we create it in our database and then I want to add one other method here which is I want to method that we can use to get the average score of the reviews for an airline so let's say for an airline we have two reviews for example and one has a score of one and one of those a score of five it'd be nice if we have a simple method that lets us quickly get the average of those scores so what we can do is just do reviews to get all the reviews for an airline and we can do I thought average and specifically want to get the average of score and then what I'm gonna do is round that to let's say two places for now and then we can just convert that to a float so now that we have that set up let's go ahead and create some seed data for our app so if we jump back into this DV folder if we jump into seeds we get rid of the example they gave us and I'm just gonna paste in some scene data and so if we take a look at this we can see that I'm basically creating six new Airlines and then I'm creating two new reviews for our first airline which is gonna be United Airlines so for each airline we're basically just adding a name and an image URL and if you look down here for the reviews you can see for each review I'm just adding a title a description a score and then the airline that the review is going to belong to and in this case they're both going to belong to the first airline that we're creating which should be United Airlines so let's go ahead and run that so I'm gonna get out of the console I'm just run rails DBC now and if you don't see any output from that then the implication is that it probably works so let's jump into our console again and let's just look and see if we have some data coulis you can see we have our first airline and that's United Airlines if we count we can see we created six new Airlines and if we look at review we can see we also have two reviews so let's just make sure that everything's working so far so I'm gonna say I'm gonna grab our first airline which is United Airlines and if you look you can see even though we only even though we only provided our seat data with the name and the image URL if we do airline that slug you can see because we added that slug if I call back method before we created this airline it actually created a slug for that as well but let's go ahead and check so we should put this airline to have two reviews and see it looks like that's all working and then I also just want to check that our average score method actually works let's say airline dot average score and we see that the average score is three which is correct because the first review had a score of five and the second review had a score of one so the average should be three so it looks like everything is working so far which is good so that basically handles everything that we need to do to set up our models for now so the next thing that I'm going to focus on is building out our API and I'm gonna use a gem for this use a gem called fast JSON API and this is a gem that was put together by the team at Netflix but if you've ever used activemodel serializer then you'll probably notice some similarities so I'm going to go ahead and install this gem into our project so back over in my editor I'm going to jump into our gem file and I'm just gonna throw this in here we can go ahead and just exit our console here and we can do bundle install to add that gem to our project so once we have that gem installed we can actually use a generator to create a new airline serializer and a review serializer and then we can actually pass along the specific attributes that we want to expose in our API so for example we can do rails G serializer now and what I want to do is create a new airline serializer and for that I want the attributes that we're going to expose on our API to basically be our Airlines name the image URL and the slug so we can hit enter on that and then Aki spin up a new serializer for us so what that's going to do is create a new serializers folder inside of our app folder and then you can see that created an airline serializer in this case and then we also want to create one for reviews as well so what we can do is basically I can do rails G serializer and then we're going to do review this time and for that I want to add the title the description the score and I also want to add let's add the airline ID for now and then we'll hit enter for that and so now if we jump back over into our code if we look inside of app you can see that basically created a new serializers folder and inside of that we now have an airline serializer and a review serializer and if you take a look inside of the serializers that just got spun up for us you can see all the attributes that we just defined with that generator or all defined as attributes here so in in review we have title description score and airline ID and then an airline you can see that we have the name image URL and slug and so for our airline serializer I want to actually just add the has many relationship with reviews so we can do that similar to what we did in our model and that's basically all we really need to do for now for our serializers so we can actually jump over into our rails console we can take a look at a quick example of how we're going to use these so let's say we have our first airline what we can do is we can actually grab our airline serializer for example create a new instance of that and then we pass in our airline to that and what we can do is basically call for example serialized JSON and we can take a look at the format that that's going to convert that into so we can do is actually take a look at that just adds JSON so if we call as JSON on that and you can take a look at the structure of the data but basically if you look in this attributes section inside of our JSON you can see that all of the attributes for that record that we specified that we want to be exposed in our API are provided here so we have the name we have the image URL and we have the slug so we can actually just as an example if we only included the name in our attributes here and if we tried that again we'd say airline equals airline up first item say Airlines utilizer dot new and pass in our airline and then call as JSON limit if we look back the attributes you can see that now it's just the name value by gennaro attributes so we can kind of control what we want to expose here by providing that to our attributes in our serializer so that's basically everything that we need to do for now for the serializers so with that setup we can probably jump over into our controllers now so for this app I'm gonna have three controllers so we're gonna have an airline's controller we're gonna have a reviews controller and then I'm also going to create a pages controller that's gonna have basically like a single index method and what I'm gonna do is basically make pages index the route path of our app but I'm also going to set it up as a sort of catch-all for any requests outside of our API and that's going to come in handy once we start using react router in a little bit on the front end so for our airlines and reviews controllers I'm going to namespace everything under API v1 and this is also just gonna help simplify things for how we manage routing from both the real side of our app with our API and then also the react side of our app once we start working with react router in a little bit so let's actually jump over into our routes so we jump down into config and then routes let's actually set up the routes for our app so I'm gonna get rid of this and then we can just set everything up so basically the first thing I want to do is set up the route path so I'm gonna set route to pages index and then I want to just go ahead and namespace our API so I'm gonna do namespace API and we'll create a block and inside of that we're also gonna namespace everything that we do to v1 I so get another block for that and then basically inside of that we can actually create our resources for airlines and reviews so we can do resources Airlines and for this actually want to specify the parameter gonna set for this I'm gonna make it slug so we can actually use that slug value that we created instead of using the ID as the primary / m4 Airlines in our routing and I also want to create resources for reviews and for this we're just gonna scope this down for now to only be create and destroy and then the last thing that I want to do here is I'm gonna actually get our new star path and then we're going to route that to our route path so we're gonna route that two pages index we're gonna do via all and what that will do is this will basically route request that aren't for existing paths predefined in our API back to our index path and so the reason that I'm doing that again is that once we start using react router this will allow us to basically handle routing to our react components without interfering with our actual rails routes for our API so I don't know if this is the best way to do this but it's an approach that I've been using that seems to work decently well and you know we actually we need to fix it should be only as a key there but now with that set up we can actually go ahead and exit the rails console here and what we can do is we can go ahead and create our controllers so we can use another generator if we want to create our controllers or we could probably just jump over into our controllers folder and actually create them ourselves if we want and let's create a new pages controller and inside of that let's just create a new class called pages controller it's gonna inherit from application controller and all of this is gonna have is an index method which again is just going to be the route path or our application so then what we can do now is inside of our controllers folder I'm gonna create a new folder called API and then I'm gonna create a new folder inside of that called v1 and then inside of that let's create a new file and we'll call this our Airlines controller and then we also want to create a reviews controller and then for each of these we basically just want to namespace these inside of a module it's gonna correspond with the namespaces that we created in our routes so it'll be module API and then module v1 and then inside of that we'll create our new class so for this will be Airlines controller I know inherit from application controller you know baseless do little bits just do the same thing for our reviews controller so let's change that to be reviews and then let's start by building out our Airlines controller so inside our Airlines controller the first thing I want to do is create an index method so all we need to do for this method is get all the airlines from our database and then render that data using our Airlines serializer so what we can do is basically just do Airlines equal airline dot all and then we just pass that value into our Airlines serializer like we did before so your airline serialize renew and pass in Airlines and then what we want to do is convert that to serialize JSON and then all we have to do is render that as JSON from within our controller method and then we can also create a method that's basically going to be the exact same thing except with an individual airline and in this case we're actually going to find the airline based off of the slug parameter that we specified as the per am in our routes so what we can do is say airline equals airline dot defined by I'm going to find my slug and in this case it's gonna be params slug and then we can basically just copy exactly what we did here except we want to make sure that we're just passing in the individual airline in this case so next we can go ahead and add a create method instead of a create method we probably want to do something like add strong parameters so we can do is create a private method and call it airline params and then we can set up basically a whitelist of the parameters that going to actually allow here so in this case I'm gonna do Prem stop require airline and then I'm gonna do dot permit and we can do here is add in all the parameters that we want to allow in this case if this is just going to be I think name and imageurl for now then what we can do is inside of our create method now we can actually say basically airline that equals airline new and pass in our airline params to that and then basically all we have to do is say you know if airline dot save so if we're able to save the record in everything's valid then we want to render JSON and we basically want to do what we did up here so we want to render JSON with our Airlines here eliezer and pass in our airline and then render that as serialize JSON otherwise if for some reason it's not valid and we can't save the record then we want to render out some sort of error message we can say like error we can say airline dot the errors dot messages let me go ahead and also specify the status if we want I so then our update method will be basically identical to that so we can do is copy that over and create an update method and the only two differences here basically gonna be that instead of creating a new instance to the airline we basically want to define by like we did in our show method so we're gonna find the existing airline by its slug and then what we can do is instead of save we can say if airline update and pass in our airline params and basically just say if that's able to update successfully then we'll render back the airline using our Airlines here utilizer otherwise we'll render back an error and then finally we also want to create let's say destroy method so for our destroy method we're basically gonna do the exact same thing almost as our update method so we're gonna find the record buys pram and then basically we are just going to say if instead about different safe airline destroy ID Emily one just render may be ahead no content otherwise if there's an error then we'll return the error with the status of for 22 which is unprocessed Ville entity and that's basically all that we need to do to set up our airline controller so there's one other thing that I want to do though before we switch over your reviews controller so when we render the data on our Airlines using our Airlines here Eliezer I want to make sure that we're also including any associated review data for that airline in the JSON payload so one way that we can do this with fast JSON API is by structuring our response as something that's called a compound document but basically all that we need to do for this is when we initialize a new instance of our airline serializer we can basically pass in an optional options hash and specify the additional resources that we want to include with that so what we can do is we can create for example like another private method and just call this options and then inside of this we can create an instance variable and basically just set that equal to a hash and what we need to do is specify the resources that we want to include and in this case all it's going to be so would be like an array of resources but all it's gonna be for now is just reviews but then what we can do is basically just take this method and when we initialize our serializers up above you just include this after Airlines is a second argument for our serializer so we want to add that into our index method and then we'd also want to add that into our show method we don't need to do that for create because we won't actually have any reviews yet at that point because we're just creating the airline for the first time and we don't need to do that for destroy but we probably also want to do that for update so let's add that and with that I think we're good for now for our Airlines controller so let's actually jump over into our views controller and this should basically be simpler than our Airlines controller because all I'm gonna create for now for this is a create method and a destroy method so what we can do in here is for our create method we probably want to use strong parameters again so I'm gonna create a private method and just call this review params inside of this again I'm gonna do parens dot require review and then we'll permit the attributes that we want to allow in here so in this case it's going to be title it's going to be descriptive and we want to allow score and we want to allow probably the airline ID and then with that what we can do is go ahead and create our crate method so for our crate method we want to say review equals review new and pass in our review params and then we basically want to just do the same thing that we did in our Airlines controller so basically if you dot saved so basically if everything is valid and we can save our new review then we want to render JSON and we can use our review serializer so we'll create a new instance of that we'll pass in our review and then we want to convert that to serialized JSON otherwise if if for some reason we can't save the review then we want to render JSON and just return an error with the reason that that's not valid so with your review dot errors dot messages I will set the status of that to be an unprocessed D and then for our destroy method basically just copy that over and we'll rename that to destroy but we want to do here is basically find an existing review by the ID so in this case we're using ID and basically and so say we just want to say if if reviewed I'll destroy so if we're able to destroy the review then we want to render probably no content again otherwise if for some reason that goes wrong we'll just render an error message with the errors for that review so now that we have our models controllers serializers and routes all set up let's actually go ahead and test out our API so we can do that using a REST client tool like insomnia or postman I'm gonna use insomnia but what you use doesn't really matter here and it also might be helpful just look at our routes that we've created so far you can do that from your terminal by just doing rails routes and that should basically show us a list of all the routes that we've created for this app so if we scroll back up here we can see basically all the routes that we set up so we have our route path here which is just slash we have our API v1 Airlines index method which is just API slash P 1 slash Airlines etc etc so let's go ahead and actually test this out so I'm gonna fire up our server doing rails s and then over in insomnia I'm just gonna create a new request I'm going to call this Airlines index basically what I want to do is just create a get request that's gonna go to localhost 3000 slash API slash V 1 slash Airlines you Ln saw JSON just to be safe but basically what we should hope to see is that when we send this get request this is gonna hit our this should hit our Airlines index method so basically we'll do is get all the airlines from our database and then we should see that rendered as JSON using the format from our Airlines serializer so let's see what happens when we submit that request cool so you can see we send that request to our API and what we've got back over here as a response is a JSON object and this is just using the format for JSON API that we'll get by using those serializers so you can see the top-level key is data and then inside of that we have an array of all of our Airlines from our database soon so the first one has an ID of 1 and this is United Airlines and if you look at the attributes you can see basically all the attributes that we specified before that and then you can also see we have this relationships object because we specify that this airline has many reviews and then because we structured this as a compound document if we look down at the bottom you can see that there's an included key that has an array of all the reviews that exist for Airlines in this case because we're returning multiple Airlines and the ID of the associated airline that it belongs to so that all looks good so let's actually let's try to hit our airline show endpoint X and for that we actually need to grab the slug from one of our Airlines so I'm gonna grab this United Airlines slug and I'm gonna create a new request for airline show and for this we basically want to send a request to the local host 3,000 /a TI /v 1 / airlines and then we want to add that slug to the URL so back in our Airlines controller when we hit our show method we should be able to find that airline in our database by the slug Graham and then again we'll just render that JSON back using our airline serial hazard so let's jump over here and see what happens when we submit that nice it looks like that worked again we have this format this time instead of an array of Airlines we have just the specific airline that we're getting the data for and then we can see because this specific airline has those two reviews so both of those belong to United Airlines you can see that we have those values in that included section in our API response so that all looks good so next let's actually try to create a new airline so let's create another request and I'm gonna make this Air Lines create and in this case we want to do is run our request to be four of those 3000 slash API v1 Airlines but this time it's actually going to be a post request that we're gonna make and in this case we actually want to include a body for our post request so what I'm gonna do is add a name here and I'm just gonna give this fake name supposed to fake airline but what we would expect to happen is that we're gonna hit our create method and this will create a new airline for us and then save it and render back JSON I so let's see what happens when we try to do that so let's submit this request I mean see in that case we actually got an error back so we can see that the status is for 22 if we look here we can see that we actually got an invalid authenticity token error back from our controller so the issue here is basically that we're trying to make a post request to our controller without a valid C surf token and rails has built-in protection against that by default so what we can do to fix that for now is if we jump back into our controller what we can do is just say protect from forgery with and we'll set this to null session and that'll basically fix that issue for us we also want do this in our reviews controller as well so let's add that and then let's jump back over into our request tool here and let's try to create that airline again so if we submit that post request again we can see that resolved the issue and now we're actually able to create that new airline so we've actually added a new airline to our database with the name of fake airline and we can see that that actually created a slug for us as well and then we can see that it has a new ID so initially we had six Airlines and we just added a seventh so we can actually do from what is we can go back to our show request and if we check now for fake airline we should be able to get that back so all that looks good so let's next let's test out our update endpoint so the airlines update basically for this we can make a patch request and let's actually make a patch request to that new airline that we just created and what we want to do is let's change the name of that as a test so I'm gonna add some JSON here and let's just say name equals and we can just set that equal to like other fake airline as of the name and let's try to submit that so we can see that that worked and that updated the name of that airline in our database and now be other fake airline and so finally let's actually test out as well our destroy bethod so let's create a new request and I'm just going to call this Airlines destroyed and we will again we'll take that new fake airline that we just created and let's just create a delete request and let's see what happens when we send that so we got 204 no content back it looks like that all worked so now if we for example go back to our show method and try to get that specific airline we won't actually get anything back because it no longer exists in our database so that all looks good so let's actually also test out our review endpoints so let's see reviews create for example let's just copy over get URL from this and we'll pass that in there but we'll go to API v1 you's want this to be a post request and we'll set up a body be some JSON we'll get this title say I will make this positive reviews will say great experience we the description as well and that'll be you know something for that I know we also want to give this a score I say we'll give that a four is four and then we want to tie this back to the specific airline that this review is gonna belong to you so the airline ID let's just make this one so before I believe it's United Airlines but then let's submit this and see what happens oh you know what it looks like there's a typo in my reviews controller so if we look at create it looks like I just mixed that up so let's try that again cool okay so it looks like that created the review for that airline we can see that that created a new review in our database but now if we go back and we get I think in this case it's gonna be United Airlines we should see we go down to included we can see yes so now we have that new review is included for that airline and then additionally let's just make sure that we test out reviews destroy and in this case we are going to basically send a delete request to I think in this case it's the third review so let's just make this a delete request API v1 reviews 3 I don't send that that also broke because I have the typo and destroy as well let's fix that so you send that that works to get back to a four note content which is what we want and now if we go back to our United Airlines request if we send that again we can see we are only getting back those first two reviews now because we deleted the third one it looks like all the end points for our API are working
Info
Channel: zayne
Views: 60,561
Rating: undefined out of 5
Keywords: ruby on rails, react.js, webpacker
Id: oyjzi837wME
Channel Id: undefined
Length: 37min 59sec (2279 seconds)
Published: Sun Apr 19 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.