We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
Analysis Summary
Worth Noting
Positive elements
- This video provides a clear, high-level overview of the Rails 7 philosophy and its specific implementation of 'Hotwire' and 'Import Maps' for modern web development.
Be Aware
Cautionary elements
- The 'magic' of generators and scaffolds can mask the underlying complexity, making the framework appear more foolproof than it is in production environments.
Influence Dimensions
How are these scored?About this analysis
Knowing about these techniques makes them visible, not powerless. The ones that work best on you are the ones that match beliefs you already hold.
This analysis is a tool for your own thinking — what you do with it is up to you.
Related content covering similar topics.
Raising Funds For World Domination (Day 318)
RobertElderSoftware
new beginnings.. (game dev log 0)
nycrat
Create a URL shortner with Clojure and MySQL
Daniel Amber
Mastering WebSockets With Go - An in-depth tutorial
ProgrammingPercy
Santa Claus on delivering 99% Uptime
Kai Lentit
Transcript
Welcome to Ruby on Rails we're going to build a demo blog to demonstrate how to get started with the framework build something real and then deploy to production let's go going to start with the creation of the rail skeleton this includes all the default directories and some stock files for you to fill in with all your content and it also sets up all the dependencies that the rails framework uses by default now that we have this skeleton we can start by generating the first model for our blog a post model that's going to have a string as a title and a text field as content we're using this generator to create the files needed for the controller for the post model for the views for everything let's have a look at what's been created the first thing we're going to have a look at is the migration the migration is what sets up the database table and as you can see here we designated that we want a string title and a text content and then by default rails also adds a set of timestamps for created at and updated ad this is then connected to the post model that will instantiate and encapsulate these database rows which again is invoked by the posts controller it has all the actions needed to encapsulate a rest style approach to developing web applications you have the seven default actions and a handful of these actions then have templates like index show new and edit i could show you one of those and that is basically all we need to get started with the most basic uh outline of a web application so we will run the migration as the first thing to set up the database and set up the post table and then we can have a look at that schema that's been generated for us as you can see now it just has the post table in there let's have a look at how that looks in the browser so we start the rails server and then we jump over to the browser and as you can see here it just gives us a nice boot screen that shows the version of rails that we're using and the version of ruby but our new app that we created with the scaffold lives under slash posts it is the basic crud app hello world we create a new post first post and when we post that it'll go to the create action which will redirect to the show action and then we can go back to the index action i've done this demo a bunch of times before and it's always looked like this it's not very nice so for this demo i'm going to pop in the simple css framework straight off the cdn so system we can have something slightly nicer to look at and i'll do that by going to the default layout that all the views are rendered within and i'm just going to pop in the symbol css styles and then let's have a look if that doesn't look a little better it sure does okay so now we have the crot actions not just for html but actually also for a json api if i do json behind the post here you'll see the entire collection currently consisting just of one element returned as json that you could hook up to a single page application exposes a public api whatever you want if we jump back and take a quick look here at the controller you can see that this is all mapped up and for these actions that create an update we have different paths whether you are submitting from html or whether you're submitting from json okay let's actually start developing our domain model so the first thing we could do is we could add validations to the post we could say validates presence of title and now if we go to attempt to make a new post that has no title we will get an error that simply says this can't be saved because the title can't be blank that error is generated by the the form html that we have the template here we have under app views posts form and see if there are any errors it'll show all these errors first and you can trace that all the way through from the create as we go through the create action we tried first to save if that is successful then find the post that's created and redirect if it's not successful we will render the new action again as an unpossible entity with those error messages in there that is a user error if you will we can also make a programmer error here and see what that looks like if we reference the wrong variable and then try to load it we can see we get this error screen in development that shows the exception being raised and the back trace where it's coming from and then we actually also have a console built right into the error screen that lets you manipulate and look at all the variables that have been assigned in there now that console is also accessible um from the command line we can jump in and start a brand new console here and interact with the main model that we've been building up if we go to first post first it'll fetch the first post that we created this was the one we created through the web interface but we can create a another one through this console as well if we do title from the console content nice we'll see you start a transaction insert into the posts table and there we have it another post object we can also create these objects for example just post all will get us everything if we want to find just some of it we can for example query on created ad we could do time now all day that'll create a range for the entire day we'll see we find still the same two posts you can see what that sql statement actually looks like in total we can try one where we don't find anything time now yesterday didn't have anything posted then that's the sequel for it and this is the empty array that's returning back okay great but having a blog that simply just accepts content as plain text is a little boring so you use another set of rails features um this is action text we're going to add to get what you see is what you get editing for our new blog we'll start here by adding the action text elements rails action text install we'll add a little bit of javascript that we need it'll add some css for the new editor and it'll add a set of migrations for us to upload and store files using active storage in this example we're just storing locally when you deploy to production you can store on s3 or other cloud storage setups it also adds an image image processing gems so we can make variants of the files that we upload so that we can get smaller versions of the images or otherwise so we'll bundle to get that image processing gem on there and then we'll run railsdb migrate to pick up the couple of migrations we have now we have to set up the model to say that we're going to use this rich text setup and do has rich text content and then if we jump to the form for that instead of having a text area we can add it as a rich text area now we just have to restart the server because we added a new gem and then we can jump over and see what our new posts look like oh we left the error in there gotta pick that out again let's do that and then reload great now you see that the content is not just the plain text field this is rich we can use rich text we can do the various forms of markups we have in here and we can even do file uploads so file uploads can simply be dragged and dropped into our editor here it'll upload it in the background via active storage to either local as we're doing here in development or with direct upload to cloud storage but we're just going to do it here rails logo and then we create the post great so now we have a post it has an image attached and if we go back to all the posts we can see both of the posts that we've put in there let me show you how the javascript for that is set up rails by default uses something called import maps which allows us to use advanced javascript without having node installed on our system we're simply using the javascript as text and serving through the browser and using esm to to deliver that this is set up in terms of what we can use in our map or in our app as this import map um the default is this stuff up here rails ships with hot wire by default turned on that means the turbo framework and the stimulus framework is already set up and ready to use and then when we ran the action text installed generator it also added the tricks and action text pins and as you can see here the application.js then imports tricks and action text and that is what makes those available to our application so that we can use it but what if we wanted to add some other javascript from npm let's have a look at that we will add a piece of javascript for localizing the timestamps that these posts were created on our blog both localizing and using time ago setups so we will use the bin stop import map and we will pin local time it will fetch that off npm figure out which url it should use based off the default cdn that we're using for this javascript that is jspm i'll show you later how you can also download that but we're just going to depend on the cdn at this time so now we've added local time to our import map let's see it right here now we can also import it and start using it as part of our application.js we'll import local time from local time and then we'll start that local time now we can use this have a look at the post here we will pop in a new bit where we can have a posted and then have a time tag and this time tag will generate an html time tag which the local time javascript will identify look at the data local attribute it says time it goes it'll convert that utc time into time ago and that's all done in the in the browser which means it's cache safe which is a lovely way to present time so let's have a look at that jump here to the browser post it ten minutes ago posted six minutes ago three minutes ago so this is all using npm directly it does not require node of any kind does not require npm installed on your local machine this is all running off a api using jsp m the cdn but you could also just add these pins to your application yourself wherever you want them they can be off your own cdn setup or it can be off any of the other cdns that are out there like js deliver but we could also download this local time instead of having it as a cdn dependency let's do that um we'll download it instead and as you can see here it's going to download it to vendor javascript local time js and when we jump back into see there we can see that that pin is automatically mapped there we just get a little comment of which version that we're using and if we jump over to the browser it works just the same great so now our little blog has posts with localized times has a way to use a trix editor to use what you see is what you get but we would also like to add some comments to this because that'll allow us to show the relationship within a domain model between multiple models at once so we'll go back to the terminal here and use our generator again instead of rails generate we can also just do rails g and instead of a scaffold we'll do a resource which adds just a thinner wrapper around the model that we're adding here we're going to add a comment and that comet is simply going to have a post references which creates a foreign key setup and a dependency in the model that this belongs to the post and it's also going to have a content that's also just going to be text as you can see it creates another migration and you can have a look at that quite similar you see it sets up the reference it will create a foreign key for that reference it becomes the post underscore id and then it has a text column for the content for us to use so let's run that migration and have a look at the main model that we've just created rails console will find the first post and that post has comments oh it doesn't have comments yet because we have not yet connected um as you can see here the comment model belongs to the post but we also need to tell the post that the post has many comments now if we pop back into the console here we can actually just reload in line and voila updates to the main model live there are no comments right now so let's create the first one it's going to have content of first comment there we go now we have a post in the system that has comments but we don't have any way of seeing that in our web ui so let's add that to the web ui jumping back in here and then going to um the post we're just going to have it on the show template on the show template here we're going to render all the comments we'll actually do a partial for it that'll be post slash comments we'll pass in instant variable of postsystem we just use local variables and let's do comments here and i've pre-baked some html that we can just pop in there we go so this will render all the comments that belong to this post this is shorthand for what you see up here we're going to render the partial of comments comment with a collection of posts so it iterates over those and then we will also render a new form so let's create those partials first we create the comment one and i'm also just going to pop that in it's just going to be a basic div that has an id which we will later use for live updating of stuff it has the comment content and we're using that time tag again with um a time ago to see when the comments were posted and we're also going to create a um partial for the new form so that we can create new comments on our post as you can see here we use a helper called form width it uses the model then we pass into it actually we're going gonna pass in local variable here um and the comment and um and there we go and then actually let's also pop in a little notice on the comment itself or on the post itself just a counter to show how many comments were uh posted on that we use one of those helpers pure lies pluralize that will go one comment to comments and you'll see that in the ui in just a second here although we also actually need to add the comments controller it starts out as just this empty shell here in order to be able to create any comments we need a create action we're going to set that up with some prepaid here before any of the actions are loaded we run a callback called setpost that will plug out the post id from the url since we know which post that these comments are supposed to be created for it will then take the parameters from the form and their scope by comment it'll require that which means that if the comment scope is not present it'll erase an exemption exception telling us that and then will only permit a allow list of attributes in this case just content says that you can't sneak anything else in you can't set a different foreign key or id and corrupt the system this is just one of those security benefits that you have in rails out of the box great let's have a look and see what that looks like we are now on post we'll go to this post and see we are missing the route that post comment is supposed to look up and that's because we i forgot to edit the routes file so the resources generator adds this comments uh resources but it's of course at the root and what we want it is to have it nested such that the comments belong to the post great see there are zero comments so far but we have our um form down here let's do let's do one comment we'll create that comment and there we go we have our comment and have a quick look at the console for the the log for this you see here we do started a post against posts slash three slash comments this is the nested route that we have here are the parameters it's using an authenticity token to make sure that we don't have any csrf exploits and as you can see here it's even filtered just it doesn't show up in the log we also filter other things like passwords and stuff that you shouldn't be putting into your logs and then you could see the parameters um this was the required scope comment and it just has one attribute that is going to be the content and what that content actually is then here you can see setpost is calling um that id the three from up here it looks it up since we have the post it proceeds then inserts the comments and when it's done it redirects to post number three and that renders everything again so now we have a blog that has posts and those posts can have comments but let's add another feature of rails let's add a mailer such that when a new comment is posted the owner of the blog gets a email letting the person know that a new comment has been posted so we use another generator for a mailer here um and that mail is going to be called the comments mailer and it's just going to have one action on it called submitted you see this generator of course does not generate any migrations just a bunch of files for us to play with so first thing we're going to edit is the comments mailer and you can see it's just a stub here we're going to be passing in the comment that we want to let the owner know about we're going to assign that to an instant variable such that it's available in the view we're going to mail that to let's say the blog owner at example.com and we're going to set a subject for this email to be new comment then we can edit the templates that go with this comment mailer that forms the content of the email that's going to be sent out so that's going to be submitted html i have one that's pre-baked we can just pop in and the neat thing here you can see is we're reusing the same partial templates the comments comment template the html template for the html part of the email as well this is how a lot of things in rails work that you can use the same templates across things like emails the first render live updates you're never recreating templates more than once and then of course we also have the plain text version of the email where we're not going to use that partial we're just going to pop it in as plain text rails has this newest feature a neat feature where we can actually see what these emails are going to look like we are going to use one of these previews and it's going to just preview whatever the first comment is and we can jump to this url in a browser to see what that looks like you got a new comment on hello world first comment that's the html version here's the plain text version and now we know that the mailer itself works let's hook the mailer up to our flow such that when a new comment is created we will also send out the email so we have the comments mailer it has the submitted action we're going to pass in the comment that is being created in this action and then we're going to deliver later deliver later we'll use a asynchronous job queue such that neither the rendering of the html for this mailer nor the delivery of the email itself happens in line it happens asynchronously much faster response time in the ui and that's pretty neat so let's um see if that actually works we'll jump over to the browser again jump back to our post and then send a comment via email create that comment and we can see whether it's been sent by checking the log scrolling back here and you can see the email is being sent it's being sent to blog owner it has that subject of new comment it's rendering a mime part for the html and my part for the clear text and if you look up here you can see the deliver later is set up as an action mailer delivery job which is this out-of-band asynchronous setup in production we would use a full queuing system rescue or something else like that in development it is just happening in line great now we have a blog that can also send email let's make this blog live and we're going to use the default wire stack or at least one part of it the turbo part of it to make adding comments a live event and it is surprisingly simple as you saw before when we looked at the application js hotwire is already configured in a new rails app so we can simply start using it so we're going to start using it by setting up a subscription to a turbo stream on the post um show action we're going to use this turbo stream from and then the name of the stream we're going to use is going to be derived from the post um since it has an exclusive stream for the comments that are posted is that and then when a comment is created we're going to let it broadcast um to the post that will broadcast both uh creates updates and destroys which we can now demonstrate so let's jump over to our browser and then let's actually make another browser such that we can have them side by side and see that this stuff is happening live okay let's scroll down here is this a live comment it sure is it showed up over here as well because via web sockets we're delivering all these updates that are made to the comments they're being broadcast whether they're being invoked from a web ui is here or if they're being invoked from the console as well since it just goes through the rails domain model so we could do here find the post 3 and then look at the comments we have those comments we could take a look at the last one and what would happen if we destroyed last one boom it's gone and it's gone because when we destroy the last one a callback is being triggered by that setup of broadcast 2 that will broadcast this turbostream element remove and the target is comment underscore id which matches the dom id we had set up for the partial for the individual comment we can also update here from the console so if we do a update of the content content uh updated from console you can see that that update is sent out as well that update contrary to the delete update is actually done asynchronously because we're rendering a template so that also happens out of band and there you have it creates updates and deletes are all broadcast automatically and of course you can tweak this and set it up to your heart consent but simply adding the broadcast to will do it for all the three actions by default when you follow the conventions okay we've created quite a lot of code let's have a look and see if we also have some tests and of course we do because all these generators we've been running have been creating stop testing that actually exercises the app and if we run those with rails test we'll see a couple of them failing we have one failing because of a invalid foreign key and that happens when we go to destroy the post then you have comments that depend on that post now having an invalid foreign key so we can fix that first by jumping back into the post model and instead of just saying has many comments we'll also say that they are dependent and they will be destroyed when we destroy a post then let's run the tests again now that test is no longer failing we still have a failing test for the comments mailer because that is of course just generated off the defaults that weren't tweaked we'll use um a fixture here if you have a look at com gml you'll see we set up fixtures for all models that are generated through the generators such that you can set up a set of fixtures that you can refer to in your text in your tests that run very fast and then i also remember we changed the subject to new comment and then we sent this to the blog owner and it was from example we're not going to match on the body right now let's go back and run that boom all our tests are passing on our new wonderful blog that does what you see is what you get editing it does comments it does live comments and now our application as such is is done but what if we wanted to show other people this application let's deploy this to production and i'm going to use heroku to do this because heroku is nice and simple and easy to use but where the rail skeleton by default is started with sql lite as the database heroku uses postgres but thankfully there is a command here railsdb system change where we can change the configuration of our database to use postgres instead that will add the postgres adapter so we'll have to bundle for that and then we can add um everything to git because that is how we will push to heroku so we'll add everything to git we will commit everything that we've added as first here and then we will create the heroku setup that we're going to deploy our app to and once we've done that we can push our app straight to heroku heroku main and we're going to get a little error here in just a second that we can correct because there is a check here and you can see this is failing because i'm making this demo on an m1 machine and heroku is not running on an arm64 so we just have to add x64 here as our platform for the bundle lock we'll do that and then we'll add the um gem file lock again commit that added the platform and then we can push again and now we have deployed our app to heroku we've been assigned the mighty tundra as our url for this and we can go have a look at that in just a second we need to do a couple more things we need to first of all migrate our database which will also set it up or we use heroku run rake db migrate and then we need to add redis as an add-on to our heroku setup because red is is used by the turbo setup to send those live updates back and forth great now everything should be setting up so let's have a look at our live app deployed in production i can use this one here and you see the page you're looking for doesn't exist and that's because we haven't actually set up a root route in our application so let's do that if we go back to the routes here you'll see there's actually a comment just for that purpose so we'll set it up so when you go to the root it'll go straight to the posts index and we will commit that setup we'll add it and commit it adding the root route and then we can push that again to heroku now that's set up so let's have a look and see if the app works in production there we go we have an empty one of course because it's a brand new database this is the first post now the only thing that does not work yet here in production is drag and dropping files because heroku would require us to set up s3 and you can use that as an exercise for the reader for you to set that up but it is quite easy to do just a matter of a little bit of configuration and then you will also have the direct uploads with drag and drop here but let's create this post and then let's create the first comment and check that everything is working here in production and there you go there is now one comment posted so let's do the test and see if we're set up and it works correctly with the turbo back to get the comments from one side to the other this is the second comment and it sure does so now we have the entire application running in production backed by a live setup that uses redis and all the other goodies and that's all you need to get going get started building something real with ruby on rails taking it all the way from hello world to who knows perhaps maybe one day ipo thank you