The Intermediate Ruby on Rails 6 Web Development Course 2020: Learn 25+ gems and build a Startup MVP | Yaroslav Shmarov | Skillshare

The Intermediate Ruby on Rails 6 Web Development Course 2020: Learn 25+ gems and build a Startup MVP

Yaroslav Shmarov, Ruby on Rails Software Engineer &Teacher

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
99 Lessons (10h 38m)
    • 1. Introduction

      1:28
    • 2. Extended preview of the application

      11:21
    • 3. create aws c9 env

      4:02
    • 4. create app

      5:24
    • 5. connect github

      1:20
    • 6. hello world

      1:43
    • 7. connect heroku

      3:33
    • 8. aws c9 get free space

      0:56
    • 9. gem haml rails

      1:38
    • 10. gem bootstrap

      4:29
    • 11. gem font awesome saas

      2:17
    • 12. gem simple form

      0:51
    • 13. scaffold Courses

      2:40
    • 14. install action text

      4:34
    • 15. gem faker

      2:15
    • 16. gem devise

      3:49
    • 17. course belong to user

      4:27
    • 18. design for notifications

      1:03
    • 19. adding a functional navbar

      2:20
    • 20. basic search in navbar

      1:19
    • 21. styling courses and home index

      14:44
    • 22. gem friendly id

      6:13
    • 23. devise trackable, users index

      8:00
    • 24. devise confirmable in development pt1

      6:21
    • 25. devise confirmable in development pt2

      1:42
    • 26. sendgrid sending emails in production

      5:21
    • 27. add fields to courses

      15:58
    • 28. gem ransack

      4:47
    • 29. gem ransack level 2

      13:27
    • 30. gem ransack level 3

      5:47
    • 31. gem public activity

      8:19
    • 32. add a footer

      6:45
    • 33. gem rolify - add roles

      8:53
    • 34. gem rolify edit user roles

      5:16
    • 35. gem rolify using role based access

      2:21
    • 36. gem pundit installation and example usecase

      4:20
    • 37. gem pundit authorization for courses

      2:25
    • 38. gem pundit only admin can edit other users

      2:40
    • 39. gem pundit user can see links only to allowed actions

      2:39
    • 40. gem friendly id for users, user show

      4:33
    • 41. check if user is online

      3:56
    • 42. add a Lessons table, friendly id, design id

      11:20
    • 43. public activity for Lessons, create lessons inside courses

      2:48
    • 44. action text for Lessons, add breadcrumbs for lesson show

      2:51
    • 45. gem pundit authorization for Lessons

      6:15
    • 46. nested resources

      7:54
    • 47. gem pundit authorization for Lessons create action

      4:10
    • 48. minor styling for edit and new views

      2:27
    • 49. production tour around heroku

      2:13
    • 50. gem exception notification catch errors in production

      3:26
    • 51. design for courses and lessons

      9:21
    • 52. gem pagy for pagination

      7:38
    • 53. add dynamic title to page tabs

      8:12
    • 54. scaffold Enrollments

      15:17
    • 55. Button for user to Enroll to a Course

      21:32
    • 56. gem pundit for Enrollments

      3:57
    • 57. gem pundit user can access his purchased Courses

      2:16
    • 58. work on Enrollment views

      16:39
    • 59. Button for user to Review a Course

      8:32
    • 60. gem pagy for Enrollments and Users

      3:39
    • 61. gem friendly id for enrollments

      2:02
    • 62. gem ransack for enrollments index

      7:14
    • 63. Navigation for student, teacher, admin

      10:39
    • 64. Collections and Scopes + Ransack + Pagy for Courses and Enrollments

      18:25
    • 65. Counters in header

      5:20
    • 66. Calculate rating for courses

      10:58
    • 67. counter cache basics (enrollments count for Course)

      6:01
    • 68. add counter cache across app

      12:47
    • 69. More course styling and validation

      9:09
    • 70. Courses index ransack sort by price, populararity, rating, newest

      3:08
    • 71. Dynamic & Personalized Homepage (Popular, New, Top Rated Courses)

      8:47
    • 72. Move logic from controller to model using scopes

      5:49
    • 73. UserCourse table track if a user has seen a lesson

      11:42
    • 74. Track User progress in a Course

      8:57
    • 75. Styling courses and lessons

      19:40
    • 76. Pluralization for course show

      1:42
    • 77. Validation for Destroy with dependent records (restrict with error, nullify, destroy)

      4:16
    • 78. Lesson show navigation between lessons in a course

      6:23
    • 79. gem chartkick and groupdate add charts

      12:45
    • 80. load charts without timeouts

      6:08
    • 81. namespace charts in routes, group by sum

      3:43
    • 82. count impressions with increment method

      5:44
    • 83. custom buttons to publish or approve a course

      21:01
    • 84. complex validation who can see a course show

      3:41
    • 85. fix nested polymorphic link issue in activity, activity styling

      8:43
    • 86. application helper for conditional styling

      4:27
    • 87. gem rails erd to generate relationship diagrams automatically

      3:11
    • 88. better views for not logged in users

      3:51
    • 89. link to courses with ransack search params

      4:02
    • 90. course specific charts and analytics, more advanced grouping

      10:47
    • 91. update course policy and view

      4:09
    • 92. 89 gem ranked model give lessons inside a course a number

      3:43
    • 93. 90 link to previous and next lesson in lesson show

      3:07
    • 94. 91 jquery ui sortable make lessons sortable and persist changes

      11:13
    • 95. 92 credentials and secret keys PART 1

      6:07
    • 96. 93 gem aws sdk s3, configure aws s3 bucket storage, add avatar to courses

      16:51
    • 97. 94 gem active storage validations

      10:10
    • 98. Next Steps

      4:47
    • 99. Thank You

      0:29

About This Class

In this course you will learn to build your own e-learning platform (like an Udemy, Skillshare clone) while learning 25+ gems and multiple Rails features!

In this course you will:

  • gain the broad knowledge and skill needed to create basically any web application you can think of.

  • get acquainted with all the modern technologies needed to find a Ruby on Rails Developer job.

  • create your own online learning platform that you will be able to monetize as you wish.

  • be granted access to the source code of the application that we will be building.

I'm proud to say that this is the most feature-rich Ruby-on-Rails-6 course on the internet

Through the years of being a software developer I've learnt a lot by trial, error, and research.

You don't have to spend all the time I did.

In this course I've summed up the best practices of using different gems and features.

You will be able to learn it all by practice!

As well we will learn to troubleshoot different issues in development and production.

We are going to build an online learning platform, step-by-step, feature-by-feature!

As a beginner you will learn the whole process of developing an application with multiple features.

As a more experienced developer, you will master features that you didn't have a big experience with.

As well, you will have access to the source code of the demo application.

This way, you will be able to launch your own e-learning platform at any time!

Here are a few topics that we will cover in the course:

Learn 25+ most popular Ruby on Rails gems:

  1. gem bootstrap and gem jquery-rails

  2. gem font-awesome-saas - library of pretty icons

  3. gem simple_form - better way to create forms

  4. gem faker - create fake data

  5. gem friendly_id - create pretty URLs

  6. gem ransack - search and filter data

  7. gem public_activity - track all actions in the application

  8. gem pagy - the best gem for pagination

  9. gem devise - authentication (users can log in)

  10. gem rolify - assign users different roles

  11. gem pundit - authorization (users can perform different actions)

  12. gem chartkick - beautiful charts

  13. gem groupdate - group data by periods

  14. gem exception_notifications - error messages in production

  15. gem rails-erd - generate an Entity Relationship Diagram

  16. gem ranked-model - order items in a list

  17. gem aws-sdk-s3 - store files on AWS S3

  18. gem active_storage_validations - validate attachments

  19. gem image_processing - display and manage images

  20. gem recaptcha - no bots will sign up

  21. gem wicked_pdf - design PDF Certificates of Completion for students

  22. gem wicked - wizard for step-by-step forms

  23. gem omniauth-google-oauth2 - sign in with google

  24. gem omniauth-facebook - sign in with facebook

  25. gem omniauth-github - sign in with github

  26. gem cocoon - nested forms

& more

Learn Ruby on Rails features:

  1. work with yarn and webpacker

  2. action_text

  3. active_storage

  4. action_mailer

  5. secret credentials

  6. counter_cache

  7. scopes

  8. application_helper, "case" and "when" methods

  9. adding custom buttons

  10. conditional validation

  11. callbacks

  12. pluralization

  13. increment method

  14. dependent restrict_with_error

  15. advanced nested resources

  16. buttons for custom actions

& more

Learn supporting technologies:

  1. AWS C9 - cloud IDE

  2. AWS S3 - store files in production

  3. PostgreSQL database

  4. Github

  5. Heroku

  6. SendGrid

  7. Google Analytics

  8. Google reCaptcha

  9. Google oAuth API

  10. Google & Bing Webmaster

  11. Facebook oAuth API

  12. Github oAuth API

  13. Stripe

Learn javascript packages:

  1. Yarn & Webpacker in Rails 6

  2. Jquery-ui sortable

  3. Bootstrap

  4. VideoJS

  5. Chartkick

  6. Selectize

If you value your time and DON'T want to spend hours learning how a gem works, consider getting this course.

By the end of the course you will feel capable of building any Web application Ruby on Rails web application.

You may learn the skills needed to find a job, or build the application of your dreams.

As well, you will build you own, complete application for creating and selling courses that you will be able to monetize.

Also, if you want to learn more great ruby on rails features, consider subscribing to this course.

Transcripts

1. Introduction: Hello and welcome to the course how to create an online learning platform using Ruby on Rails. Now in this course, you've learned how to create a complete, fully functional software products from start to finish. My name is Chiara and I will be leading you through this course. Now, I'm proud to say that this is the most feature-rich Ruby and Rails six goals in the internet. You will learn how to use more than 20 most popular RubyGems, as well as multiple Rails features. So we will start from 0, from a blank application and we will build up functionality step-by-step, feature by feature. We will go through all the details are breached text editing that action texts you belonged to store files for the active storage and Amazon S3, and what secret credentials are and how to use them. We will also create advanced role-based access management functionality. The course includes generated PDF documents, sought, and records in a list, creating charts, searching, and sorting data as well. You'll understand how to add JavaScript packages with gone and the backpacker. In the end, we will make our application ready for production. Following the course, you will create your own online learning platform that you can put the market anyway you like, by the end of the course, you will. Who comfortable working with Ruby on Rails six. And you will be capable of creating high-quality web applications on your own. So feel free to look into the course description and I'm looking forward to seeing you inside the course. 2. Extended preview of the application: So in this course, they're going to create an online learning platform that teachers can create courses and upload content and students can enroll the causes and view the content, view the lessons. Now, at the moment we are on the homepage of our application and we are not locked in. And we can see how many causes book created, how many teachers there are, and how many students there are, as well be considered most popular courses based on the quantity of enrolled students. Right here. We consider top-rated courses, the ones that have the highest rate. And first, we can see the latest courses. We can see the most popular course tags, and we can see reviews loved by different students. Now, if you want to sign up, we will need to pass our email, our possible muzzled confirmation and Dick recapture that you're not a robot so that the automatic emails and bots cannot send up to the application. A user signs up. You'll also need to confirm his email at his email address than the, than the login node we're going to look in as a student and as a teacher. So this user has locked in and he has the role of a student and a teacher. How can we see it? The go to my profile? And we see that the teacher and student and our email has been confirmed. Now, we have two types available. Learn and teach will started loan. So here you can see the courses that you have purchased. So you see that you have purchased this two courses. You see a course search bar. You can find the course, you can see a list of all courses. Now that tried to search for a course. So let's type ruby. And we see all the courses that have Ruby in their name will refresh and search all the courses that have developed software in that dogs. So software, let's try Ruby dust, whatever. You can search courses by title, by the name of a tag, by the description, by the language and visual causes conducted by the price or buy the email of a teacher. Now, here is a course that we are not subscribed to do. So we will open the calls. And we said that there are two lessons in the course. We see the page of the course. We said that description, we see the details, we see some kind of additional description of the course. And I'll be C2 lessons. So let's try to view one of the lessons. And you simply cannot do it because you're not authorized opponents action because you have not enrolled for this course. So you need to enroll to the course and to be able to see that lesson content. Let's try to enroll so the press free. Now, this will be a page where you can actually create a payment provider and you can pay 0 if the course is actually pretty so repay. And now we have enrolled to the course. And we see that the can already review because we've enrolled to the calls and have 0% of progress in this course via because we haven't viewed adolescence. Now, we can see which lessons we have used and which ones we have not as well. We can see how many comments. It's less than half. The content of one of the lessons we've seen. Here is the content of the lesson. Now it just kind of random taxed at the moment that we can leave a comment. So we've created a comment and we can go to the next lecture. And here we have a sidebar that you see all the courses in, all the lessons in the course. Now, here is the content of the second lecture. You said that we can have a video and you can have everyday or thumbnail right in the beginning. We can add any kinds of contents. We can add the videos, photos, music, or whatever. So we have already 100% of the course. Fantastic. Now the go to the teach tab. We can create a course. So let's create a title. Nava can create an avatar, basically any image. So I'll select this image for example. Lets have some kind of description. And you see we have reached text editor and they're doing it with action taxed. So we can upload any kinds of files, photos, videos for whatever. We can make it bold. Now we can have a short description is for marketing purposes. So we can select a language of the course, become slightly levels. They can select the price. It can be either 0 or any price that the user selects and can make the coast published or unpublished. So if it is published, it is visible to the audience. If it is not published, it is not visible as well. We can select tags from text that already exists. We can start typing. So let's type ruby and facilitates that have now gone to create a new target that is not Ruby on Rails, just Robot wildtype at rubidium. And here is a new tag. We can select a few different tags and create the course. Now, all the images and videos are stored on Amazon S3 storage. We will also learn how to connect. So here is a course that they have created and there are no lessons, no reviews. Let's try to adolescence. So and at some kind of content, now we can add a video, we can add a video thumbnail or just add content attachments inside this field. So we create the lesson. And here's a lesson. They see that as a course creator that there has been, only been unique viewer of this particular lesson and there won't any impressions acceptable u. Now, if we refresh, there was all the debugging Prussian, one more afresh. There are two impressions. And each time a user opens the course and we'll count how many unique users have seen that lesson. As you see, we can also use breadcrumbs. So vc causes the name of the course that we're looking at now and the name of the luxury that they are looking at now, for it to be easy for us to navigate, you can edit a lesson and visit that we can also see it in our bread crumbs. So in loan BC, once again, the courses that we have purchased and our progress in each of the cause and the causes of turbulence review yet. So they go to planned and review and we see that we have not attributed this course. Now we can add a review, sorry, press attribute. And we can add a rating from one to five. So let's give it a rating of five and great goals and great instructor. And the update. And we see that this review was posted to concede on the course page. Here is the course page and we see that the reviewers both did not have to lessons. And what if we want to change the order, not become changed the order of lessons that do not belong to us. So if this is not our goals, you see it's not persisted in the database if we refresh. But if we go to my courses, we go to our calls and we have been lesson at the moment. Let's create a second lesson. So here we have two lessons. We see that the second lesson was also added to the navigation. And now let's go to the course page. And we have this two lessons taught. If you want to change the order, you can just drag and drop the causes from one place to another, refresh. And we see that the, it has been assisted in our database so we can change the order of our lessons inside the course. Fantastic. So as a teacher, we can also see my enrollments. So all the users that were enrolled to my courses, the look at it from the admin page. So designed out and login as an admin. So now I'm logged in as an admin. And you see that I have an additional admin tab here. I have unapproved courses. So these are courses that for already finalized by the instructor, but v-nought approved by us, meaning that they are not visible in the list of all the courses. Now as an admin, you can approve or an approver calls. So here is a cause. For example, Jiang discard calls. I open it, I press on the proof and the goals is not approved anymore, meaning it is not visible in the list of courses anymore. Now, we can see all the users in the application. So we see that there are three users. You can type the email, search and find uses by email, they can see when the user was created, how many times he signed in the IP addresses that he sent in from, and how many courses enrollments OER Commons the user has as well. We can see if the user confirmed his email and we can see the roles of this user. So we see that this user is an admin and teacher and the student, the second user is a teacher and student. And you can access different parts of the application based on his roles. Not We can take one of the roles of a from the students. So let's update and this student. So let's go back. So this user is only a student now, and he will not have that teacher tab anymore and he won't be able to create courses anymore. Now, we see all the enrollments in the application and all the enrollments in your own courses. So you'll see the email of the user that signed up to your goals at the name of the course that the user sent up to how much he paid. And if he rated the course and left a review, you'll see his review and his rating. As well. As an admin, you'll be able to see all the activity in the application. So you will see what actually was done by the user and ban. You'll see who created a lesson. Goals and enrollment advantage was done. You can as well paginate from one page to another to see more activity actions as well. You can moderate tax as an admin so you can delete tags that you do not like, and you can see how many times each type was used as well. You'll have access to application bite analytics. You will see how many users registered, but they have many new enrollments for credit per day. And the most popular courses and many more different analytics. As a teacher, you will also have access to cause specific analytics. So if we go to the schools, crass analytics, we will see how many enrollments for credit a day, how much money it enrollments brought. And we'll see what molarity and the other statistics on each of the lessons in the course. So this is the main functionality and there is much more. You will learn everything about storing files in a Ruby on Rails Six application, troubleshooting. Everything you need to deploy an application to production correctly and much more. 3. create aws c9 env: So for this course, we're going to do our development in the cloud nine on AWS. Basically, cloud nine is an online IDE. Vi becomes greater containers and inside the containers make however we want to develop. So first of all, we're going to create an environment. Let's give it a name. So RubyGems, okay. We will select Ubuntu server. Next step, nothing here. And we are creating the environment. It will take up more memory to load. Ok. Now our environment has loaded and let's get familiar with it. First of all, they are going to close everything that we don't need. Here we have the terminal. Here, we have the file system. As we see it's empty for the moment. There is a README, but when we learn to use it, so I deleted. And let's see what we have installed version. We see that we already have a Ruby version pre-installed. And trails five is also pre-installed, but no, they're going to update it to the latest version. So IBM list to see all the versions of Ruby that you have installed. And they're going to install the latest version that is to 7-0 at the moment. So let's have it installed. Next, we are going to set it as the default version that we are going to use. And do have some more free space vaguer to uninstall the versions of Ruby that we are not going to use. Oh no, we go to IBM list and we see that we have only the latest version of Ruby installed. Next we are going to install the latest version of Rails. So gem install rails. And this will also take couple of minutes to load because it has to load all the gems and all the dependencies. Nobody have rails installed. And let's see what's next. So we are going to run gem update trails and Jim update system just in case to see that we have the latest versions installed. Okay, so we do have the latest versions. Next we are going to install young for web diagram, as we know, Rail six rounds with the backpacker and it needs young to be installed. So we are going to run these commands. And we're going to run the command to install postgres SQL. And Young was Glasgow is the database that we're going to use for our production in our development. We have these installed knowledge check our Rails versions once again. So Rails and Ruby. So we have the latest version is installed. And we can also run this command to check the version was grayscale that have installed the database. So we have also latest PostgreSQL installed. Basically, we are ready to create our first Rails application. That is what we are going to do in our next two awesome. 4. create app: So now we are going to create our first Ruby application, and we're going to run this command. Basically this is a basic command to create a new application. Rails knew this is the name of the app. It's going to be RubyGems and they are going to use the database PostgreSQL. So around to create the application. It will also take couple of minutes then been drawn for the first time in a new environment because all that necessary gems needed to be installed. So we've generated our app and all. Let's open it. Ok, bundle. Now I saw something yellow, different Madonna. So we are going to uninstall synchronous data, going not going to need this Chung. And also I'd like to clean the gem file. So just make it look cleaner. That African that both commented. It will be just deleted. Ok, it looks much MOOC liminal bundle. And let's try running the application Rails server. Let's go to Preview, Preview run application open in the browser. It tells us an error. So we need to add this in our development environment. So we are going to Development dot RB to make the search I pressed Control E. So whenever I press control ie in the Cloud9 IDE, I go into the search. Brodmann RB. We add this configuration and we restart the server, Rail server. Let's rerun it. Ok, role Ubuntu does not exist for PG. So now we need to set up the gene. We are going to run couple of commands for this. So we are going to create a user name it. Yes. Exit. Okay, let's try once again. Okay, the database does not exist. Now let's run rake db, create. Okay, created rake db migrate, but most likely they will be nothing to migrate, so nothing will happen. And funding the Rails server. So here you see what we got out of warnings and blow them up based on Ruby to 7-0, most likely they abundance will disappear in the next version. So we managed to run our application that we have just graded. But Rails now runs with a backpacker and we need to also configure it. So we type yawn. So we are adding the node modules. And we're also going to open the web back a file. So conflict about Becker go down. So we're going to use port 800, 82 and public. So not localhost, but we're going to use this preview rule. So this phone, ok. And this will be deleted. And now let's try running racquetball. Okay, so invoked notes, try running this command. Basically, Becker is installed. We are done with this lesson. Let's try running the sober once again. See that we have couple of volumes and to get rid of the Spartans can also run the server with such a command. So without the depreciation and without the experimental warnings. So let's try it on him like this. You see that the discriminant b then get all these depreciation and experimental volumes. So they are restarting our server and everything works without them. That's it for this lesson. 5. connect github: Okay, now we're going to add our new obligation to git hub. So we're going to create a new repository, but been named RubyGems. And now we're going to add this new obligation to our GitHub. But for this, we need to add some global variables for GitHub. So chromosome is going to be a name Yaro and my email so that it identifies me. I just type this in gold. So next commands are git, init. Okay. They're going to add all and get the ad. Oh, so you could just coping, get first comment. Econet come this repository. And they're going to push it to master. So you see that we have added our newly generated application to GitHub, and in the next lesson we are going to push it to Heroku. 6. hello world: Okay, so we've created our application and now I have only this basic FirstPage. And all we're going to create our first view. So we are going to create something like a hello world. So rails generate a controller named home with an action index. Obviously that somehow has been created and now we have a new view. So we go to views, home, index and HTML page. So let's also added to our roots. We will add a root. So it's been the open our obligation VC, not this page, but the home index page and the gold, the Rails server. So we see that now if they're wrapped, asked to our new traded page and we can change some information on it like write Hello World. You see that it has changed, okay? Nobody's going to save the things that we've created. So we'll get started to civil. We have created the monster. Okay, so we've committed our changes. And in the next lesson we are already going to push this to Heroku. 7. connect heroku: Okay, so we want to add obligation to production for this, we're going to use Heroku, but fit into first install Heroku. So they're going to run some commands. The one that we have here, also oldest commands to have everything installed for heroku. You can bake. Okay, now there are going to create the new obligations. So great. So I'm going here. I am with my Heroku credentials. Okay, so we've created this new application. We're going to rename, rename Trojans. Rubygem that almost taken. Let's think of a name, something like okay, Eric who's taken I don't convert outfit and you'll name let's say something like something like this. Oh my God. This isn't taken. Okay, we've created our Heroku application, and now let's have a good status. So there is no common that we didn't run in GitHub. Let's push it to github, git push. Okay, we're pushed up to GitHub. So we have two comets and we are going to push to Heroku, git, push heroku master. And now they're going to add our application to Heroku. It can take awhile. Ok, and it took quite a while to install a new app in Heroku is because of that Becker and y'know, that also needed to be installed on Heroku. So let's try running then you Heroku application. And we have our application to Heroku and anybody can access it at this URL. 8. aws c9 get free space: So when developing your own cloud nine, with some time, you will see that there is no free space lab. And to fix this problem, you will have to run this. Yes. Basically, they will clean up the pallets that you do not use. So you see we have reclaimed two gigabytes of space. And what's gone? Yes. Okay. And novel check our sevens. So we will put those Aquatabs removed PHP support. I've come and go as we're not going to use them in this particular course. Okay? And basically, remember these commands for cleaning opera space with Daniel that implement them in your environment. 9. gem haml rails: So now they're going to install the jump humbled rails. Basically, humble is an alternative multiplying which do HTML that provides a Kleenex indexes. So here is our hello Built HTML file. And now we're going to make it hung. For this, we're going to install the Humble Jame. Let's go see how it's done. So we just installed a jump here and the bundle. And we're going to build that ERB files do HMO. So basically before we had HTML dot EIB and we are going to have HTML dot HMO. And the inside of the file, it's going to be generated. So let's try running the command. You see the HMO version of the file was also created an auger going to delete that dot ERB duplicates. So instead with the humble file has been created. And here's how it looks. Let's try running the server, Rail server. So here we see that it runs. For example, let's try nesting in humble. It's really easy for this. We are going to use spaces. So H-bomb, Hello World, and the paragraph. So let's see. It is a both nested under H1. It works often than developing in humbled, you belong to convert HTML to humble or humbled. Do HTML police? There are a couple of useful links, like the subsidy HTML Duhamel that I often use for development. Then I will take an HTML goat snippet and don't it into HMO. 10. gem bootstrap: Okay, so now we're going to install Bootstrap for our front end and to discourage Asian bootstrap, RubyGem, let's install it. But first we see that we have some uncommitted changes. Promptly told the installing the humble game, so let's commit them. Ok, now let's installed in Gu Jiang. So we had GM Bootstrap to our gem file and bundle. Next we are going to use this short guide that I've created, two also near the jQuery rails gem bundle once again. Then we go dot assets, stylesheets, don't application CSS to SCSS inside the file, delete African and add to this. Not going to add this polynomial. So we imported Bootstrap and all we need to add the bootstrap, jQuery and Poppa Jazz too young for this. They are going to run this command. Okay? Nobody going to environmental JS. And they're going to make the file look like this. Okay? And we're going to tax obligation, but JS and they're going to import bootstrap. So let's import the bootstrap on the bottom. And let's see how it works. Rails server got compiled and let's restart the server and what we will be seeing. Okay, you see that the font has changed. It is the standard bootstrap formed. Basically Bootstrap is broken. Let's try using some of the Bootstrap classes. For example, a cold. So we created a code. It works basically not have bootstrapped running. And let's try some of Bootstrap's additional modules like nav bar. So Bootstrap navbar. Let's take a random Navbar HTML to humble will convert this HTML to HML. Let's take this and put it in the file. Let's see how it works. So we'll restart the server once again. No. As you saw when I press the drop-down, it didn't folk. And it is because in the environmental chairs, I didn't add this module, exports environment thin. So let's run the server once again. It's compiling. And let's run it. Okay, so the drop-down spoke. And it would mean that all the bootstrap components work. Let's save the changes. Let's push. Okay, that's it for this lesson. We'll learn how to install bootstrap Hermitian rails. 11. gem font awesome saas: So now we have deployed our application to Heroku. Let's see how it works. Guarantees. We've got an APA dropdowns that broke. Nice. And the next thing that we are going to do is install Font Awesome. It's a really beautiful icons that we will be using in our application for this list Font, Awesome, Sauce, Jiang. Let's install it. So they get a jam and it do our gem file, Mongol. Ok. Next we add these files to application dope SEA SCSS. And must be pretty done. So let's run the server. And they'll try adding a couple of items to our application. O plus adapt flag. Now it's compiling. Let's fade. Okay, so we see a flag. What other icons have the God, let's say going to add an Amazon logo and let us see the Amazon logo. The goat is FAB, aphasia, Amazon. So in Hamlet for beam dot FAB dot FA, Amazon is works. Now let's say we want to add a link that would be a Font Awesome icon. So let's make link. Let's say rule of law. And let's add an Amazon I can present, but let's add at home icon. So afraid FA, home. So we have a link that will take us to the home page with folks. And let us also add this to get home. So git status. So the comment will be jumped from two awesome sauce. That's it for this lesson. 12. gem simple form: So now we want to look at our first scuffled. It is going to be a course table with two fields, a title and a description mode. Before this people, the post add a gem called simple form. Basically, it is going to make all art forms Luca defined for Bootstrap. So let's open the channel and let's install it. So via opening junk simple form in jump file as usual, adenine bundle. And they're going to run this command for Bootstrap that we are already using. As you see, it has created gut logo initializers and they're going to be used for our scaffolding in the future. We're going to see much more powder jam is used with our forms. 13. scaffold Courses: Okay, so now we are going to find this coupled alcohols, but first flew at everything to github. Github. Okay. Now let's run the scuffled. I haven't already prepared somewhere. So not around in the scuttled. I'll let C migrate into the database. So rake db migrate. So it has been done. And now let's also add a link to the courses. Select would be something like Link courses and it'll be a book and we'll write courses. And we'll also add a gloss. Would be a bottom success bottom. Okay, let's run the server this compiling. Okay, so we've got the link to our course. Here we will have the list of our courses. We can make the table look better. We will just open the index table is already much better. And now we are going to try creating, creating the Corso dipole description. Okay, IT folks. And now we will add some validation. So we go to post.rb and we will add validation for presence so that it cannot create a course with a blank fields like this. But we will add these basic validations. Ok, so null, then we create a new cause. We will get okay, boggling. Yes, because we are not using body, we're using description will restart. Okay, now given us, the arrows would need at least five characters for description, and it goes great. Our first scuffled. 14. install action text: The next thing that we are going to do is add some rich text editing for our descriptions. For this, we're going to use that tricks text editor. It looks like this with some rich text features. And they are going to use action text in Ruby on Rails for this, it is pre-installed with Wix editor in Rails. So how are we going to do this? Basically, we go to the console and type in the command to install action text. Let's see what that gives us. Okay, so it also gives us two migrations, Bumppo action text and Bumppo active storage that is used for it. So now we're going to application.rb S. Tricks and action text are already installed automatically to go to Action text dot SCSS. And at this line to embark tricks. And now if we go to our goals dot RB and type him has reached text for description. Okay? And the next thing that we're going to do is in our views. So in our form, we are going to add, the poem feels they're going to use HTML to howl instead of the description f dot. So let's try restarting our server. Oh, but before this we are going to run the migration, rake db migrate to new tables and rails server. Okay? It is not content, it is description. It's compiling. Okay. Now for some reason it didn't work from the first time. Let's see. And it is so because I forgot to include that action packs in the application dot CSS file. So let's write once again. So it'll go compiled and we see that f and beautiful title description with any kind of content. So let's try it. Let's try something else. Violet link. So let's create the coals. They said that it works. So that's how action textbooks, basically you get it installed and it works really well with any kind of fields that you want to make a reached, a text area. 15. gem faker: The next thing that we're going to do is populate the database with some fake data. For this, we're going to use the faker gem. So we go to Jim Baker. Here it is, basically provides different kinds of fake data that we can use for our seeds. For example, different kinds of data connected with addresses or with anything else. So let's get it installed. So we go to gem faker bundle. And I'll be, we'll go to our seeds file and add some fake data here. So, so we're going to add a generate that will create the 30 courses with a title from faker educate the hostname. How did they get this? I vented faker default, educator. And basically there are some ghost names like Criminology 1.0.1. So it's going to create random Coase villa random course name. And we're going to use games or thrown quote random bomb in the description so that strong seeds and we're going to add these fake data to our database accordingly. Let's run the server. Okay, if folks and we see that we have added 30 more records. Let's see how many we've got. We'll go to causes index each bond. How many causes have you got? 34 courses. Nice. That's basically how you can use the faker gem. And there are many kinds of data points that you can generate, phone numbers, emails, anything. 16. gem devise: So now we are going to create a mechanism for authentication, meaning for users to be able to log in and log out and they're going to use that Devise gem. So let's install it. You take it the gem devise, go to our gem file and bundle. Let's see what's next. Rails generate, devise install. Let's see what it gives us. Okay, there are some things that we need to do. So they add this to development RB. Okay, next, you make a route home index, but we already have a route home index. And next we add this fall messages. So we will convert it to humble and added to our application. We'll go to app. Let's call this dial sheets views layouts application. We'll edit before yield. So here. And what's next. Okay, we're not going to generate the automatic views. We can do it later. Next, what do we have? Rails generate devise model. We're going to use User modal. So rails generate devise user and the screening AS in-migration to have a users table rake db migrate. So it has created users and basically to have to be authenticated to save application that can address before action to our application controller. So we go to controllers, Navigation Controller. And this usual load, the roots. Good, it has added device for users automatically. And let's start our application, Rails server. So because we have added the before action, authenticate users to our application controller, it will require authentication for any action that we want to do in the application. So you see now we have to sign into CNF em. So let's create, Okay, let's sign up. We've signed in and we consider courses. Now let's add some buttons to see the current user and to be able to sign out, they're going to just add that this piece of text to our obligation HTML. Let's actually create an navbar. So let's run the layouts of bomb. And let's create another ball actual name ID header. And let's add these links here. So if there is a current user, it will show the username, actually the email. And there will be a link change that boss vote. It is at the vi's method. And to sign out also if the user is not sent info bubble to either log in or sign up. So let's try it. Okay, the city's links. So obviously the current user email, we can change the password and we can sign out and visit those buttons on top. This is the most basic usage of Devise gem. 17. course belong to user: So now we have a course modal and the user model, and they are going to create a dependency between them. So a user has many courses across, belongs to users. They're going to run the migration uses two causes usable on stone. Let's see how the migration looks. Here it is. And we are also going to add a user to seeds. So user created, this will create a device user and they're going to make each goals that we create belonged to a user. So go Mom, and this must happen. Let's try running the migration. So I will drop the database we had before because we're using, let's see, we're using the null false, meaning that we would have an error for the courses that we've already created before. Before that did not have a user. As long as they're working with a development environment and they're using seeds, it's fine. So I'm dropping the database behead, I'm creating. Once again, I'm migrating and I'm doing the seeds unknown attribute user for goals. Let's see. Let's try like this. Seed. Ok, it felt a validation because the email has already been taken. Because we've already created the USA, but we didn't create the courses because they user ID killed was solvable, common this, and run the seeds once again. It must convert, let's uncomment it for the future. And John, the server. So let's see our courses. We've created an admin. Let's see the email. So, you know, they're signing in like this. So we have 30 courses. And now let's see if they belong to this user that we're going to edit in our views. So index. So they don't have a user. Now let's create the relationships in the models. They go to the modals, loans to user a and user. So they're going to add a basic deaf 2S is gonna be an email and has many causes. Let's try once again. Let's go to the course's index and make it just calls USA demonstrated email. It works. Now let's try creating a new cause. Then if we want to create a new cause, we get an error because of course has to belong to a user. So they're going to make the user automatically assigned as the current user. And we create a course. For this, we go to the courses controller and go to the create action. And let's try now. It variables. And the current user was assigned to the cost that we have just created heritage last course. So now we've created a relationship between the user model and the cost model. And when it causes created, a user is automatically assigned to it demanded created the course. 18. design for notifications: So now we're going to talk a little bit on styling. Our application knows not even the messages. They are going to create a new layout for these messages. Are going to paste this code here. And we're going to go to the application view, render the slave. Let's try how it works. Let's run our application Rails server. So you see it is already highlighted in red color. Let's try deleting the copays. And once again, you see only the bounded from wanted is left when the try login in and it gives us a success. So it looks a little bit better. Now we've added this messengers. 19. adding a functional navbar: So now to make our app look better, they're going to add a new navbar code. This we're going to do in the old Nepal that we just copied from bootstrap. And in the place where we have this header, they are going to place this code. This is a network that I've developed using Bootstrap, Font, Awesome, and device that will eat Voc for any app that has these three jumps. Let's try running it. So here's the navbar. Let's give it a name. So the name of the UDL be RubyGems. And here we have a homepage. It goes page, a search field that you make work in the next lesson. The modelling that would be on the outside and account settings, the possibility to sign out, sign up, log in. Basically, simple Nalepa that talks about and that can be used in the mobile view also. So let me explain you how highlighting the active link verbs. Here is the code. Heavy have an active link and how does it work? The link is active and the font weight is bold if the current page is, and we decide what the current patient B, for example, with courses, we highlight the link if the current page is goes to spot. That's how it works. So let's see what we have changed this two files and now to make the page look a bit better, let's add everything inside yield into a container. Let's run the server. So it's in a container and it looks already slightly better. Now we can commit the changes. That's it for this lesson, internationalist and they're going to learn how to make the search Baroque. We're going to look for a course based on its name. 20. basic search in navbar: So now we are going to make the search work. Now. Basically now going to be searched for something. It just takes us to the root path and searches by a name. So let's see how it works. We have a form tag with an getMethod and go to root path. But we want to search for causes and they go to the causes path. And we are going to search by title. So when we try, once again now, physician causes by the title, but we didn't do anything in the controller, so we do not have any results displayed. They're going to modify the controller. Basically here we are going to have method for index. So if the title params, then they're going to search for courses that had a title that contains this part of the params. Otherwise, we're going to show all the courses. Let's try once again. So we're shown the odds. Let's try as do nine. Okay, let's try something else. Remain. So we found the criminologists, and that is how simply we made the search Voc in the header. 21. styling courses and home index: So now they're going to do some more work on style. And first of all, they're going to add these two lions to the application, HMO, the header so that everything is rendered better in the mobile views. Next, we're going to create a new view for courses. So we created a new file, ghost HTML humble, and we're going to create a new view for the course, is going to be in a call. There will be a header that the course name and the course title. And thats going to be called body with the course description and a god. But other information. And how are they going to displaying this cog? So we're going to create a new view here. I mean, they're going to render the cost is not in a TableView, but in a different kind of job. You're going to have got columns and inside we are going to have these gods. So let's see how it works. This is how the cards are going to look. Here are the chords, and here's the table. So there is some difference. Now let's get rid of a table. But we'd also like to use these links. So let's add those links to our card. They're going to be, let's say in another folder. Let's add one more photon like this. Let us see how it looks. Ok. And now let's style these buttons also. Let's see how it looks. Ok, looks quite fine. Okay, so nodal add some styling for the Dion and butter. Now let's add some icons. For the gospel show a MOOC. Let's find some kind of icon for a user as a teacher. So they're going to Font Awesome icons, checking the prevalence. Let's check, check both teacher and that's what they are going to use. So let's see how it looks. We've got time for the course created atom. Maybe clock will make note FA, but at a regular. So also looks nice. And we'll add this on. Different levels. So we'll put a rho between the time and within the user. Looks not that bad. Knowledge. Check how to look for some styling in the description. Let's see. Update calls back. And on the bottom. So looks not bad. Now we want to be able to open the course. So let's create a link. Cause let's see how it works. Now we go to the coast, but they also wanted it to look nice here. So what are we going to do? We're going to also render the scored in the coast show action. First. Delete the actions that we are not going to use now. So the JSON JBuilder balls and going to show, and here we are going to render. Also. Let's delete what we've got here. Let's see how it looks. Okay? It doesn't find the Braille book calls, so now we see that it is passion that navigation. So we'll add some kind of paragraph. Looks fine. So we are going to the courses there showing the goals. We're going to remove this two buttons, edit and back. Actually instead they are going to add something that could look like breadcrumbs. So it'll add something like link to top. And here we'll have, let's see how it looks. Here will have a more linked to this course. So here you have got it. This current course. Here we have something that would look like breadcrumbs to also add one more paragraph here to make it look nicer. Not bad. Now, on the bottom we have this new course bottom. We are also going to put it in the header. So they're going to the course's index those and move it from here. And they're going to put it in the header. So they're going to layout header added somewhere here. And also make similar design as poll data items. So link_to. Cool spot, spot goals. And let's see how it looks. So here is a new course button and we can change a picture. They'll do something like FA, loss. So something like a course. So we have a course button, we have a button to add. A new course. Looks nice. Now let's go to our homepage. And we're also going to work on styling it. So they're going to the homepage. And what have we got here? So we will add something like a jumbotron. Let's see how it looks. Okay. Kendall have something like Levelt also FSH filled here. And just go to the search field. We will also make this text bigger. So we've got the search. They are also going to move it a bit lower. Not bad. Ok, now what do we want to have on our homepage? We want to invite people to learn different courses and Toronto see different kinds of courses. So they're going to have something like a list of popular courses. So popular causes, top-rated causes. The most recent. Divide those, they're going to remove this bottoms that yields the samples. I'd say it's a bit too big. But here we're going to render the kinds of courses. So they're going to go back to causes index and they're going to run these courses. So we don't see this courses because they then declare what causes are in the home controller. So we go to the home controller and they're going to have different kinds of courses so that we'll have, first of all. Let's try now. Yeah, so now we see all the courses, but we don't want to see all of them gone to see a limit. Let's limit three courses. So they have three popular courses through the credit courses, three most recent causes. But they are not really at the top rated bonds because we can trade causes yet. They're not popular because we don't see how many people applied for the course. And yes, we can actually make the most recent causes visible here. For this, we're going to make a sep, separate action. Recent courses. They are going to use. So we're just going to add credit at older. So let's refresh. And here it will seal that most recently created courses in the most recent forms. Not just named them latest courses. Going back here, name, naming them latest causes. And here we will also declare latest courses. So the causes here and the causes here already slightly different. Let's add something else. So we're going to add something like this. And it's going to look so, so we will see how many courses we have, how many instructors? So how many unique people credit courses? How many people there are in the app registered, and just something for marketing. What else do we want to see? Maybe a person who's logged in and who subscribe the cortical bone to be able to write a course and to see the courses that he has applied to. And also in the future, we will want to see the categories of courses and the most popular ratings for the courses. We're going to work on that in the next lesson. One more thing, they're going to make it so that a person who is not blocked in consider homepage. So for this going, home controller and they're going to add this line. Let's try restarting. Now. Com controller skipped for index. Let's go home. And we see that we can see this page without even login into the application. Now we see that when we press the logo, nothing changes, it just adds fascist sign. So for this guy going to that header and we're going to replace this with this time. Let's try one scan. Yeah. So when we press the logo, we go back to the homepage. And now we'll add some most known for the course form. So they are going to the courses. Then you action. They're going to put it in a code. And the body tag we are putting the form. Let's see how it looks now. And same with the edit action. So let's see how it looks for the edit action. So it folks, and they're going back to the course page, and this is how a ghost looks. So this is it for this lesson battery developed on Scotland homepage, island courses, pages and styling the forms. 22. gem friendly id: So now they have nice cause views. But when they go to the URL and we see that we have the ID, of course, visible. It can cause a security threat as now as delta uses how many causes that actually are on the platform? That can be not always the information that you would want to give as well. It doesn't look really fancy. Haven't communications for nine to, in the oral would make it look better. For this. We're going to use the Gemma friendly ID. So let's see how it's used. And we add the gem to our Gemfile. Now we are connecting. It happens sometimes on cloud nine. It shaken for your credentials. Soviet reconnected. Here is our gem file. We are saving it. And they'll say what's next. So next bundle. And next the credit emigration to add a slug field to our causes modal. Basically, a slug field will be a field in which the new auto, they'll be stalled. I'll show how it works now, the Adam, this migration. And as vowel running the migration to generate friendly ID. Let's see our migration. So here is the first migration that we're going to add a slug field to causes. And horizontal migration needed for friendly idea and they're creating a table for these slugs. Next we are going to run rails db migrate to migrate these two new migrations. And then they're going to at the frontline ID information to our causes modal. So they're going to modals cause. There are going to add these two fields. So extent triangular ID to the application that we are going to use it and friendlier id title. Next, we are going to need to add friendly ID to our controller. So they're going to our courses controller. And before we will find in by prompts ID. But now they're going to find perhaps a friendlier id. Basically it is telling us that they are going to search for a database engine, not by this ID, but by the slug field. So let's try run on the server now. Okay, and let's create a new calls. Okay, let's see how it works. And you sit up. We've created a course and it has a beautiful oral here. Let's go our courses and we see that only the new cause, the V created has a beautiful idea. Let's use this one, for example, to make the old courses also have a beautiful idee. They're going to, they're going to run this command. So we are going to save each course once again, and it's going to generate a friendly ID. Now, it didn't fail. Of course, because I didn't run the console. So there are no, not the server but the console. And they're going to type this command in advance again. So to save an older causes false exit and now and running the server, let's refresh. And here we see that it has generated a slug education 5-6. That's the most basic way for using friendly ID, Jim. And now all the courses have beautiful poodles and style. We can use some more code to generate the other kinds of ideas. For example, it doesn't have to search by title, but and searched by a field that you create or buy something automatically generated or random. So for example, if the use such code that we generate a random number and use it to have the sludge generated. Let's try one scan. So they're going to the courses and create a new course and visited a random number of losses. Given the course, it's really good for transaction information. Now, they're going to commit the changes, but we are going to use the title for parental ID in our case. So status, we see all the files that have changed for us to install the friendly IT chum. Good. So in this video, we've learned how to use the jump premolar ID. It's really simple and will give beautiful naming to your database entries. 23. devise trackable, users index: Now they're going to go back to users. So we've created a user model that the jump device, but we don't see a list of whole users they're going to edit. Now, for this, we are going to create a new controller, is going to be uses controller. Inside the controller, they're going to add the regular stuff. And they're going to make an index view. So it will grab us all the users. And they're going to create routes for it also. So they're going to config routes. And here we are going to add resources for users. So here the added resources for users. And we're going to need the index action as well. Here we are going to solve the users by their creation date. And let's create a view for the users. So they are going to create a new folder, put it under the views directory. And inside they're going to create an index view. Here is an index view and inside they're going render our cards with our users. So we are going to have called the columns courses, and they're going to have a list of users and gender calleds with users. So let's create for more view for a user. And inside we will create a call. We are using the Font Awesome icon for a user. So they're going to show the email and inside we're going to have some more information. So we're going to use the time go into birds method to show how long ago a user signed up. I'm going to add the Ago. And that's it for now. Let us see how it works. So we are starting the server and we'll also add the users to our header. So let's cope with wonder if they had with courses. It uses pulse. And let's see how it works. So here we have users. Okay? An initialized causes controller. Maybe we made a mistake here. Yeah, here we have home controller. I just copy pasted. I should have put users. Let's try one scan and it fills Mozilla user_data we have created. It is our current user. Now, we want to work somewhere with the Devise gem and see what else it gives us. So, for example, trackable and confirmable. Let's civil trackable does show how many times a user signed in and other interesting information. Let's add it to device now. So we are going to the device documentation. I didn't trackable to our user dot RB. Now here behind it. So it will be able to see their IP address and other information about the user who signed in to our application. The migration. Let's see how it looks. Okay. I'm going to add this following fields to the migration right here. So they are running rake db migrate. And let's see the fields that we've added. So they are also going to add them in our uses index to see the values that we have in these fields. So we are going to our user view. I didn't feel more calm. And we're going to add this information. So user and this values. Now let's restart the server. So it shows us 0 because all these fields are empty for us at the moment, let's try creating a more user sign-up. So we've created a new user example, and we go to the user's list and we see the values of these fields. Let's give them some name and for us to understand what they are. Let's see if it folks humanized those folks. In the meantime. Let's try differently. Okay? I've added the braces, says and IT folks. And now we just need to add some roles so that these fields are in different trolls. And here it is, we've added the device trackable fields to our user table so we can see the current signed in, how many times a user signed in, and the IP addresses. That's how device trackable works. 24. devise confirmable in development pt1: Next what we're going to do is add confirmable modal for device. Basically, it will not let a user used application unless he confirmed his email address. Now we're going to look at the documentation for it arose at the documentation file. So they're going to add this confirmable set into user_data right here. Next, we're going to create for more migration for divisors. Here it is. And here we are going to add the following columns. So let's see. We're going to add confirmation, token, confirmed at conformation sat at. They're going to add an index for it. And for the users that already exist, they're going to confirm all the email addresses or as of now, so that the people that use the app before, they'll still be able to use it without having to confirm the address. So they are on the migration. And we can go to the device RB To see more Sutton's. So to go to devise search for confirmable. And here is the configuration. So here we can set a setting for how long they want a user to be able to use the application without confirming his account. Here is how much time a person has to confirm his account. And if so, let's try running. A server will create a new user. It gives us an error. And here is phi. If we go to the migration, they initial migration of device, and we see that we will need the unconfirmed email field only if they're using their confirmable. So they're going to devise drag confirmable. We see that it is true, but we are not going to disable it. Instead we are going to add the unconfirmed email field. So we are going here. They're going to undo the last migration, so rake db rollback. And they're going to add this field. So they're going to add the column is going to be string and the field is going to be unconfirmed. Email. Nice. Let's try once again. They are running our server. Okay, let's try one scan. So example three. Okay? You see that a message with a confirmation link for some, it is automatic device message. And you said that the person doesn't automatically logged in. So he has to first confirm his email address to log in. Let's go see the message in our locks. So here it is. You can confirm your account through this link. So if they cope with this information in the braces and pasted here, it will generate a conformation. So the user has been confirmed and he can log in. What was the email again? It was Example three. Looks good. Now, after v confirm the email, they don't get automatically logged in. Usually, it isn't the standard approach because login in after confirmation automatically can be considered as a security threat. We can work on this feature later. Now, let's see the list of users that have their emails confirmed. For this, we're just going to go to the user. So here is our user. And here we are going to add to fund more footer to check if the email was confirmed. So if the email is confirmed, the Field confirmed until the present, otherwise, no. Let's see. Okay, so all these users are confirmed. Let's try creating a user and without confirming him. Ok, and let us look into somebody who is confirmed. Lock in. So they go into the users and rescinded that user was not confirmed thick and not access the application. This is it for this lesson here the learned how to use devise confirmable. 25. devise confirmable in development pt2: So I just tried looking in like this that an account that I've created before and it tells us that we have to confirm our account before continuing. Let's try resentment the conformation instructions. So they are putting in our email and descended, let's see it in the logs, the email that we just sand. So they are going to the logs, let's make it a bit bigger. So here is the email falcon. You can confirm your account at this link. But we want to replace localhost with the actual domain of our test environment. So they're going to development RB and they're going to replace the local host for the environmental we've got here. So for this link, they're going to Edit right here. And we will not need to port 3 thousand. Ok, now let's restart the server. Rails server. Okay, let's refresh. Okay, and let's try resenting the conformation instructions once again. So resend. And let's see where it's Sunday. So it's unto the right link and it will be run to the link. It will show us that we've confirmed our email address. So it folks, let's try login in. Here. I've entered the app. We can see our user confirmed email. Yes. So it folks. 26. sendgrid sending emails in production: Hello. In this lesson, we are going to learn how to send emails in production. So at the moment we can sign up or log into the application, but you've signed up, they won't be able to access the application without confirming our email account. It is really good for security and for people not to access the application with a random emails that looks somehow like this. So to make it work, they're going to add an add-on at Heroku and the other is called Sanskrit, is basically a helper for us to send emails in production. There are two ways to add this. So you can either go to your Heroku dashboard, open the app that you want to add, the semitone, click Resources and write the name of the episode. Send crib. When you write the name of the app, you'll be able to either choose a paid or choose the free plan. Most likely, you will be able to use all you will need to use on the free plan. It lets you send around 10 thousand emails per month. And in most cases, it is enough about the problem of the free plan is that it might take couple of minutes for the email to be delivered. It doesn't always deliver right at the moment. Press provision. And the second way to add semi-arid is we'll look at the Heroku documentation for Sandy grid. And here we see the command heroku add-ons, add sent grid, starter. So we can write this command here, varies it, and run the command. Now I've already added Sanskrit, so it gives me an error, but if you run the command, it will work. And next we're going to configure our application to voc, the standard grid. So first of all, we're going to our environment, our beam, and we are going to add this code so that Sandec invokes. Next we are going to production and introduction. I'll be there this following lines. So that default oral options are going to be our core, sago herokuapp calm or W name your app at Heroku. Basically, the confirmation instructions will be sent to this host and it's really important that you add the name of the domain of your application here. Next burger into this, technical things as performed delivers true, raised, deliver error straw, and look for a method, SMTP. Next we're going to devise, and here we have this mailer sender. So here we are going to add our I'd add an email address from which this emails kind of come from will write something like support the core sago herokuapp.com. Let's add it here. So Support at Coursera herokuapp.com and in development are being, we're also going to add this action mailer delivery method does line. Okay, now let's also check our application mailer file. And here we can also add a default portal. So here we'll write coursera dot herokuapp.com. Okay, now I'm going to share the good status. Okay, we've made changes in all these files. Now, you must push your changes to GitHub and run git, push heroku master to push the application to Heroku. Now I'm going to pause and going to push to Heroku. Okay, so I've pushed our changes to Heroku and have our application at the moment if you have just one user registered, and now let's try to add a new user. So I'm going to use this e-mail address and I'm going to press sign up. Okay, and message with confirmation link for sent to your email address. Now I am going to this email address. Let's go here. So I don't get it yet. Desire a couple of old confirmation emails that I received while testing. Okay. I received a trill or fast non-present confirmation instructions. Confirm my account. Okay. Your email address has been successfully confirmed. And now let's try login in. So long in our email address, our possible log in, OK, the managed lock in. And as you see, we have all these actions that we can perform. Now, once again, this user and the VC that this user is locked in, this user is not logged in and he did not confirm his email. Now let's try logging in with a user that didn't confirm his email. So we'll take this user sign out and log in. So email, possible login and you see the person can't log in because he needs to confirm his email. Now if he goes to his email address and confirms that it will be able to log in. So in this lesson, we added the ability to send the emails in our production application using Heroku, sand, grit, and device. Jim. Thank you very much. 27. add fields to courses: So now they're going to add some additional fields to our course modal, short description, language, level and price. So let's run the migration at feels to causes we will have than language, then level and price. So they're going to have a price as an integer and we're going to use the money. Jump for rails in the next lesson. And in this lesson we are going to talk a bit more on simple form, the jump for editing forms in Rails. So let's run our migration. So here it is. Now let's add some defaults. So for the level, for the language, the default is going to be English and the field cannot be null. For the level. The default is going to be a beginner. For the price, default is going to be 0. Okay, good. Now they're going to run all migrations. So rake db migrate. And let's add our fields to our controller. So we're going to invite list them here on the bottom. Short description, price, language, and level. Let's clean it up a bit. Now, let's run our server. And they're going to try to create a course with the new kills that we've added. So they're going to add them to our form. They're going to accuse causes form, and they're going to add these fields. So F, input, short, description, language, level, and price. Let's see how it looks. So we can alter the address fields. But actually dislike of this checkmark on the side. As valid, they're going to make a default view for the Submit button. So for this fair go into our simple form, bootstrap, sudden. And they're going to add a button class. So we are going to button success. Let's see how it changes. We'll restart our server for the __init__ Generalize it to initialize and visit us. We have the bottom that is now a successful surplus. So if we want to edit the course, it will also have a success clause. Okay, and visit up. They go to the very bottom of the screen, but don't vaunted will also go to Application HTML and add a break. Okay, so that we have at least a little bit space on the bottom. Not they're going to get rid of these checkmarks. To get rid of this checkmarks there go into our application, a CSS. So assets, stylesheets application. And they're going to add this code here. So for the form control is valid and invalid. They're going to have no background image. Let's restart the server and try once again. You will see how it looks now. Okay? And the buttons are not cone. So initially I added the coat of the running application. Now to add into the right phone repression and visit it. Awful checkmarks have disappeared and try doing something that the validation doesn't let us visit. That simple form gives us this prompt. So now we're going to work on selecting a lungfish, selecting a level and selecting a price. For this, we're going to the simple phone documentation. So Jim, simple form. Let's see how they address collections. Collection, bought one. So that didn't dare collection like this. Okay, so Collection Australia, Brazil, New Zealand doesn't exist, looks like this. Let's try an indoor form. So don't to select a lungfish with a collection. Beginner, intermediate and advanced. Let's see how it looks. So go into edit and we can select beginner, intermediate or advanced equal to. Let's do the simple languages. So we will have English, Polish, and Russian as an example. Okay? And the same for price. So, oh, actually the price can be just anything for now. Here we have a rich text editing for description, but no rich text editing for the shot. Because we don't want a lot of text in the short description. And then they're going to actually have the short description displayed here, but they opened the cost will have the long description also displayed. So let's make it visible. Now we have the causes and don't see the price, the language, and the level. Let's make them also visible. So they're going to the course. And Q, Yes, our cause. And let's add these. Now. Let's see. Oh, course called Ok, let's actually make it look not like a book but like em, like a creation capital. So let's go. So let's make it red you, let's see how it looks. Looks good. Okay? And they're also going to add degradation gap in the header. So better place in the book for degradation couple. Okay? And now they're going to add the price, national description language and difficulty. And so they're going to create one more called full-term goals. Goals level and goals price. And for course, prosper. I shall go on to use numbered currents and method. Let us see how it looks. So English beginner, $0. Let's also make it look a bit more beautiful. Let's check the Font Awesome icon that film to use for language and for level. So Font Awesome icons language, and we'll do a little bit language. Let's select a globe. And the four course level we will choose a signal sign. Let's see how it looks. So VT_2 and the price. Now let's see what else we can choose for the level. Signal is called. Now they're going to replace the description of the, the short description. Okay? How does it look? Now we're going to add new fields to seeds. So they're open seeds are B. And they are going to add this new fields. Short description, language, level and price. Let's go back to the faker gem documentation and select something that people wanted Bolton. So let's choose a boo. Let it be whatever. Now, okay, not a boo. Let's choose a quote. And let B ym, famous last words. They're going to add that for the short description. Then for the language, we're going to sew for the language identifying human language. I will add the program in the bomb. Let it be like this. Then level will be beginner and price. So the price is going to be a random number between the buttons that I have added here. Okay? Now it gives us some errors because it then put a comma here. So must look good. Now let's try to run our seeds and the control them without the user. Rake db, seed, Rail server. Let's see all our courses. We've added some new courses and we said that some of them haven't. You saw descriptions, some have none of them. And here is some random value information. So languages, all our beginner, and all the bands that we created just now have random prize assigned. Looks good. Let's actually make some additional validations are going to cause our beam and the Virgo and to see to it that the short description is always present. So title, and now I need to reconnect after connected. So they're going to say that the short description is always present. The language, that price and what else? And the level. Okay, so let's try creating a new course and visit it. They also have them now in the validation. So the concrete, a course without a price, that outer level and without a short description also. Now visited when using simple form, dont get automatic error messages for the rich content because it is not an input field, it is custom Ruby on Rails field. So we are going to add this additional form input error message. And let's try once again. Yes, ANOVA also gotten description on the plank. If it is blank, Let's try credit and you cause so Ruby gems description of whatever. Short description also languish. Let's like the language advanced course, Bryce 500, create. So here we've created this course. So in this lesson we've added additional fields to our courses. And just for a little bit better, they're going to go here and add the price in a separate footer. They're going to center it. And also they're going to put the language and the level on different sides. So we're going to add a row and they're going to put it into two different columns. Okay? And they're going to put this text, right? Okay, looks good. And they're going to do the same for the creation date and for that teacher. Novel just put the price and bid higher. So looks good. I think it's enough for this lesson. 28. gem ransack: So next step, going to add the rents a gem to our application. It is a wonderful gum for searching for information by fields or for filtering. Yes, how it works here is a table, for example, and we can filter by email. They can search by both title The consumed by an email. You can search by any fields. So we're going to add this to our application, the go to gym run suck at it in that jump file bundle. Next, we go to our users controller. So these are ransack methods. Basically, we're going to search for the user based on the parameters that we add and the split us out the result. Ok. Now, it will be much more beautiful if it looks like in a table so that you can also sort, let's add a table like this. And here is going to be our search form. So, but it I gave here, I do the search form. I took search field and took a submit button. So half of the search form for our fury heritage, the theory, we're going to search by the e-mail and we are going to submit, and this is just a separate link to take us back to the user's path. Let's try it out it, let's start the rail server. Okay, let's try it on scan. So we go to our users. Let's try assertion by the email. Ok, here is the email than to go to Admin and we get the admin. It works. Now let's just add this additional link. Let's refresh to be able to go back to be cynic. Yeah. So just a bottom to refresh our page for just appointed to point into our uses buf. Okay, next we're going to add the filtering. Let's see. So here we have this salt link method. Let us try taking it from here and add it to our table. So sort link by email, refresh. Let's try. So it gets sorted by the email both in the Top Cops. And here. Looks nice. Next we are going to try to search by bond or two fields. So we are going to also search by the sign in count. Let's add them Morefield. So one more search field, sign-in count equals. So this contain method and this method run sick methods. And the contains is for strings and equals r four integers. So let's try it. The refresh. Let's add actually a place holder. Frost No, what we're searching for and here position for the email. So placeholder email. Let just look for the indentation. Oh, okay. Refresh. So email, admin, sign-in count one. We don't have such users. Let's just search by the sign-in count 0, they have the admin, okay? Not verbal. Merge this two such fields into bonds. So it will search either by email or by the same account. So we're going to add one more search field. It will be in male or sign-in count. And here it is going to be email or sign-in count contains. Let's try now at min. Okay? The guns search this way because you have an integer and a string in Bonn, same place. Let's try with equals. So let's try it 0. Let's try. Let's try. So it works. In this field, we can drill a search either by the e-mail, sign, encounter. 29. gem ransack level 2: So now they're going to add the RANSAC to our courses. Let's go to our causes index. They are going to create a separate column for its so great row, column. And we are going to base our coast list into another column. Let's see how it works in the server. In the meantime, we'll also need to modify that controller. So the copilot in that users were going to comment it here and replace users but causes. Let's see how it works. So we're going to have some extra free space here, VAB, we can base our search. So we'll cope with the assertion that we've got in users and place it right here. Let's see how it looks. Okay, but we don't have email. So we are going to use the fields that they've got in their courses. So title, contains than forgot to show description. Done bottles have got language. We've got level, and we've got price. So price is an integer loop. Equal level contains, language, contains and will also change the placeholders. So language and price, let's call it looks okay. So they are going to make this bootstrap input fields min and fill out a form control class. So clause form control. Okay. Now I will remove this form inline thin. Okay, so we see that now gives us some space and let's make it small. Or actually not. Yeah, because dolphins the jump. Let's go to this clause and added to all our other fields. Here. Let's see how it looks. Ok, looks a bit better. And here we'll have courses path will not need this margin. So let's try and criminology. Okay. It found as all the criminology courses, we are repression. We say, oh, our courses will look something like 1.2.3. The seed that choosing a price is 0. The sea on other courses that are free. Refresh level, big bell, nothing. Beginner. Okay. So this is the first step of adding the sidebar search for courses. Okay, first they're going to add one more field physician by a user email. So they are going to search by air relationship modal, how they are going to do it. They're going to check the RANSAC documentation. Includes. So we can add the relationship includes method. So we are going to add includes. And of course belongs to a user. Meaning we're going to add includes user, result includes user. And it's not going to be distinct true anymore. So we are taking this one out. Okay? And we're going to create one more search field. User email contains. So it's already a deep relationship. Search field. You have a user, because it goes belongs to a user email. A user has an email and contains. So let's check. Let's add a user email. And let's try searching. So let's see if that causes that belonged to somebody who has an E admin has not, have all the admin courses. Let's create a course as the Yushin user. So to create a new cause, create, now they're going to all causes list and going to add this search and we found the courses that Yushin has created. So here we have a deep forensics search. Next, they're going to make this a select field so that we can select a language and not just type it in. So for this we're going to add select field and it's going to look something like this. So instead of a search field, you'll have a slug. And they're going to slight the language contains and they'll use the available languages. So let's see what languages they have in our course form. English, polish, Russian. So let's make it English, Polish, and Russian. Okay, they're going to comment this fund and have, have such a small search field so we can select English MRSA causes an English Russian silicosis in Russian and folks. Now to make this collection in the index field view and in the form, always be the same. They are going to add this language lists to our post.rb goals dot RB. And they're going to add something like this. So languages and have, are going to have all our languages sovereignty. A search for goals dot languages will have all this arrow array of three languages. Now let's edit to all form. In the form it looks somewhat like this. So input languages and the collection will search for course languages. So let's see how it looks. If you go to our course form. And here we have a language sled for English, Russian, and Polish. Let's add the ML language, let's say Spanish. And we have, also have Spanish. Now let's also add this to our goals search right here. So they're going to the index view and we're going to have something like F, select language, collection calls, Dot languages. Let's see how it looks. So here we have three languages must have in the collection right here, and here we have all the languages that we have in our list. Actually, we don't need this collection thin for our search so that you don't just have caused languages. Let's see how it looks. Yeah, yeah, I'll new languages, they're going to delete the old view like this. And also we are going to show delivered just for reference. And they're going to do the same for the level. So we go to calls and at the same four levels. So levels, level, level and levels will be fish bonds. We have, let's see. We had beginner, intermediate and advanced. Intermediate in their immediate and advanced. Okay. And we are also going to have this in the form. So we're doing the input level collection caused levels. Let's see how it looks. Now we have an error, cause levels. Okay, here it is. So we have the three levels. Let's try a new level. So we have it here. Now, let's also add this novel. Delete the one we don't need. And they're going to add this collection to our index. So same as we have the languages we're going to edit for levels. So it's going to be a level contains goals, levels. Let's see. We're going to cause. And here we have the three levels now we want to add blank also allow blended Qu. Sure, let's see. Ok, it didn't work this way because it must be include blank. Okay. We have it here and I have it here. Let's see how it looks. Now let's refresh. So now we have the blanks. Let's try searching the causes that have Russian and that are intermediate. Don't have any Russian beginner. None Russian Without You have been under this advanced. Okay. Yeah. So we have just one in Russian and it is advanced. Lets choose only advanced. Yeah, there's just one course. So the Selected Works. Now we'll add some labels to our search fields. So let's make it look like this. Description, language, level, prize and D term. Now let's also make it so that if you don't see the whole email hopeful and user that created air goes but see just the first button. So it'll be kind of a username. For this, we are going to go to user dot RB and create a username method. Okay, and here we'll put something like this. So if a user has an email, they'll have an email so we don't really need it. It's going to be the e-mail and it is going to be split by this sign. So the first part of the email before this sign, let's try to see it in our course. So let's go to the course HTML and replace user by user name. Let's see. Dot, dot username looks a bit cleaner. Now, if we want to search in the top navbar, they're going to get an error because the top is assertion by, let's find the cause controller. By this. And the bottom we have Ramsar. So here we have Brahms title, but we're not going to have this queue. And in the next lesson we're going to add the search bar on top that will replace that search bothered to have. At the moment. 30. gem ransack level 3: So now we're going to go even more advanced and we're going to add a search field in our header using RANSAC. For this, we're going to use the advanced mode and the Reynold going to do it just as they wrote here, they're going to do it in a slightly better way. So you see that here we can use an oral to which our search is going to be redirected. So what do we want to do in that application controller and add a global variable for us to have our courses. So it's going to look somewhat like this. So if the user is signed in, the search is going to broke and there'll be a global variable as runs it causes. So here we are going to have causes RANSAC. And according to the documentation reports. So we set a variable as courses search and search key causes search. Next they're going to go to the header and header we're going to add instead of the form that they had at the moment, some code like this. So you see here that we have the search form for and have this RANSAC courses variable that we have all the courses. So as core search and oral causes path that wherever they are in our application, if we put something in the title field and trust search banner, they're going to be redirected to the courses off. And they're going to use this goal Renzi courses that we've got to set up in our application controller. So let's see how it works. Let's refresh heavy on. Let's try finding the cost wildtype Vance around five. It does not fair, OK, but doesn't work. Let's try here. Been 75. Okay, this one works. So because we don't have the same a searcher varibles setup in our courses controller CTRB solely by courses but in the application of research by RANSAC courses. So we're going to make it look similar. Now causes controller is going to look somewhat like this, so it will come in the thing that we had before. So instead of Q is going to be run some courses for the courses than params, go search and search key causes search according to runs. So courses. And we are going to use this runs of causes variable that we have here in our search form. And we're going to include the results user as we did before. So just instead of q, they are going to use RANSAC courses here for us to have more visibility or what we're doing. Let's see how it looks. Ok, now it gives us an error that causes index. We have a search form for q, but in the controller visit, Renzi courses not q. So let's also edit it. Our course's index here. And instead we are going to put runs courses as cause a surge, UDL causes path. So the search form is going to look like this. That's come into what we had before. And let's try one scan. Okay, let's try to look for a course in the new navigation von 75. Okay, we found the Course says that have been 75. And you see that here it also at advanced 75. So these fields are identical. Go to anybody else in our application. Type, creamy, for example, and it finds us all the criminology courses. Fantastic. Let's try searching something here. So odd. It finds us all the odd courses so nobly have RANSAC search in our navigation, we can as well make the search work not only on one attribute, but we can search multiple attributes. For example, become we can go to our header as not only a title, but the title or short description contains. And let's type something like date and gives us the ones that have tape. But you see that here it doesn't give us the same thing. So we don't have tape here or here because we don't have such a same field that has a title or description. So that'll show description for example here, refresh. It also gives us tape. I'm going to, they're not going to use this session to parameters in our navigation, so delivered just like this. And that's how you use the runs in navigation. And we can even get rid of this other kind of associates we had before. Let's try it out. Okay. So let's go here. They're going to know whether they're going to comment. Okay, this search is going to be hidden and they're gone. Here. They're going to get this out like this. So we are going to comment everything that we had here. Just like this. Let's try now. So find the course. Madison works. Let's try logging out. Oh, okay. Signing in. Okay. So our RANSAC in the navigation works. If you just press search with nothing, they're going to go to the closest path. 31. gem public activity: So now we are going to install a gem called public activity, and it'll help us track each action that was ever taken in the application. So whenever somebody creates something and it's something, we'll delete something is going to be saved in our application. So let's add this jam, just an example of how it can look. So gems public activity, they're going to our gem file. I didn't this gem bundle. Okay, so in our models, we are going to include something like include public activity modal. So we are going to our courses modal, let's find the courses. And we are going to end this, include public activity. Nobel reconnected. Include public activity. And now let's see what's next. So we must add these migrations. So rails generate public activity in migration. Let's see what it gives us. Okay? So it's creating an activity is stable and basically it's going to be a table of where they're going to track each activity ever taken in the application. So there is an owner cone min minimum data here we can have the current user, for example, in trackable, they're going to help the cause or the lesson or whatever is being dragged when we're creating an activity. And the key is going to be great. Update, Delete over W1 and parameters will be infinite. Else would like to add on top. Let's migrate this rake db migrate. Ok, we've created this migration. Now let's try to create a goals and see if maybe you've got saved OK. Rails server. Rails server. So public activity and creating the creative knowledge, see if there was a public activity created. Console, no observer, but they're going to go the activities that we've got. Okay. We don't have any activity Seattle. Let's see why. It is because I forgot to include this feature. So let's go to goals and also add the threat. Let's edit to this course and see if we track it. So we will stop them abdominal. They're going to RubyGems, rails server. So the edit this, and let's see if that was connectivity created. So obviously that an activity was created. Now we'd like to display all the activities that we've got. So we are going to our home controller and we're going to add, the more they're going to have public activity, activity. And this activity is okay, now we are going to create a view for it. You're going to be activity not activities. Okay? Next we need to add a route for this roots. And we are going to get home activity. And let's add it to our header. So we are going to have a patina of contiguity. And here I will have a bell and hear activity. Let's see if it worked. Okay. And there is no such path as activity both. Let's see the rules that we've got. Roots. Own activity, and that's what it is. Home activity POP and home activity, Bob. Ok, we are repression, the sea activity. And we don't have anything here because our view is still empty. Let's go to our view. So if you haven't gone to add activities, beach, eveything, d v d. Okay. And activity ID, let's see the shoulders and have an activity with ID von Hippel have something like Herder. If a team. Okay, so we have an activity and get an idea bomb. Let's add something else like an activity, which other fields that we have? Let's see. Activity checkable, checkable type, and checkable ID. Let's see. Okay, then we have the only field and have the key. Let's add the key. So we see that the core 63 votes updated. Let's add parameters. If there are any. And let's add an owner. Okay, no, only up. So now we can display activities now that make it so that an activity belongs to the current user issues, so that we know that the current user did this activity. For this, we are now going to go back to the course and to modify the struct slightly like this. So instead of just track, they're going to have tracked owner. And we are going to find the current user from the controller. So if a try once again, they're going to our courses that take calls, for example, the one that we just edited lost. Save it once again. Okay, we don't have a current user. Let's see by most likely because we have one activity without a current user and the other bids. And referring to the documentation, I shall understood that the program both because VD and include this public activities token children, our application controller for this to work properly. So we go to our application controller. They're going to have the public activity still controller. And they're gonna draw inference again. Okay, let's see our activity. And we said that the second activity was created by this user. It looks nice. So let's just make it look a bit better. Okay, so each activity isn't in a separate show. Now to make it look nicer, they're going to add something like this. So linked to the activity trackable. So we'll have a link to the scores. Okay, looks not bad now. So in this lesson we learned how to add the public activity region and we save Egypt pivoted done by any user in the application. Each grade edit or delete for the courses, specifically in this lesson. 32. add a footer: Okay, now we're just going to work a bit on styling our application. So we will first go to our header and move vacuum divided from here to here. So here is our activity. And if we're going to move it right here, instead of that link facility, this open, our users are causes novel make the activities look a bit better. For this, we're going to use bootstrap. So we'll go to bootstrap and see what we like to use. So we will use this list group. Yeah, they're going to have activities displayed in such a list. So let's go to the style HTML to HML. Okay? This see how it looks to our activities. Okay, we're going to have a list group where this is all going to be mastered. And each will have such a clause. So like this. And this will be all nested inside. Now let's see how it looks. Looks already butter. Now, let's also make this look better. So they are going to the activity header to tech center. And activity is cone. They're going to put it in a nice bulge. Info. Okay? And we're also going to make it bigger. So h, h, h2 will be fine. I like H three mole. Ok? So we're going to have such kind of header for each page. They're going to all users. Users index. And here we are also going down. So you had about 50 users. Users count. And with courses. So we are going to causes index. So courses and courses count. Ok, it looks fine. Actually, we can also do with a small paragraph here. Let's make it be, just be OK. We'll edit in all the other views. So have the habit here. Save, save uses courses and we'll edit to activity. So activity index. Okay. It looks quite fine. Now let's go and see what we have on our homepage. So to have our popular courses are top-rated courses, our latest courses. And maybe somebody else now have a search field here. Let's see if it still works. And doesn't work because we deleted the controller. It felt soulless scene. Controller, courses controller and controller. Here's our courses controller. So this kind of code that made it folk, it would mean that we need to add a new button, that negative space. We're just going to go to our header and cope with the search form. So we're going to our header, I mean to our home index page. And here we are going to try to add this runs a form. So here's our answer phone actually had the same text find the cost of the old form. So when we search in RANSAC, we get an answer. Find out here. Ok, we are going to get rid of the old form. They're just going to comment it. Ok. And what else do we want to do here? Yes, they're going to have an error. If the log out. You see we need to have the global search variable, even if the user is not logged in at the moment. So they're going to add this search field only if you have the current user. Okay, I've got the if statement. So if currentUser, then they're going to have it. Looks fine. Now let's also add a footer to our application. So they're going to our application HTML HML. Here it is now layouts. And they're also going to run the footer. So on the very bottom ran the layouts. Footer. And they're going to create a footer layout. Okay? And we're going to add some code here where we will add something like this. Let us see how it looks. Okay, we've got a footer. Looks fine. Knowledge also added some kind of color. So it will look like background, let's say success. For now. Let's see how it looks. Let's give it a green background. 33. gem rolify - add roles: So I've restarted the application and I've deleted everything that they had in the application. Now I'm going to create a new user. So let's have such user. Okay, I must get an Message with confirmation. So I'm going to my console. I see this message, I'm opening it and I'm login in. So I've logged in. Okay, now I am the only user in the application and the runt and it causes created. And what we are going to do in this lesson is learn how to create role roles for different users. So they're going to have three kinds of users that are going to be admins, that are going to be, there are going to be students. Admins can do everything and see African students can not create courses, but they can only learn and psychosis and teachers can not see analytics, can not see the list of all users, cannot do it, causes that don't belong to them, but they can create courses. So for this we are going to use two gems, the roller phi GM and wanted gem. So Jim Rowley phi. And this jump is agenda that we are going to use to give users roles. So a user can have many roles and the sum going to be just a Boolean as admin, true. And Jim bonded. So and it is an Authorization Gem, meaning that we can give each controller action a permission. So for example, only admins and teachers can create courses on the admins, can delete causes. Only students can view courses. It's I'd say something more comfortable than that. Can, can, can jam. So let's go ahead and install these jumps where they can qualify. And going to the jump file and bundle. Okay, next we're going to generate, generate, qualify for the user. Now let's see what the Gables. So it's inserted something to user RB. Let's see what it gave us in user RB. So it added this rarefied thing for the user. I'll just put it on the device. Then. It gave us a role model. So let's go here and see rho dot RB. Now at the end appear here. I'm going to refresh the application. So now we consider role model. What does it give us? It created a rho phi initializer. So rolling file dot RB and Created migration. So let's have a look at the migration. So in this table we are going to have all the roles that we have in the application. Because in theory, not only a user can have a role, but any other modal can also have a role. Looks OK. Now I'll just make this look a bit better. Okay, let's run the migrations, rake db migrate. So here we have this error. They're going to try to make it not just an active record migration but 6. Let's try rake db migrate. Ok, it worked this time. So let's go to our console, rails console user account. So let's see how this works. Let's go to the methods. So let's add role admin to the user. Let's see if we are going to, now we're going to delete this and we are going to set the first user as user. Now they're going to add a role admin. And let's chuck. So does the user have an admin role? Yes, he does. Okay. So now users can be given an admin role. Now let's see some more methods that rho phi suggests us to use. So it suggests us to give a roll to a user as after His created. So let's go to the user. So other creative assign default role, and he's going to be given as rho as a student. Okay, now let's try creating a new user. They're going to do it in our application so they are certain the Rails server sign up. Oh, okay. Let's confirm the account. Let's sign in. Okay. We've signed in and want to see whether the user is that if the user has a role, we are going to make it visual. They're going to add this visibility to our users. So let's go to user. If we're going to go to the pews, users, user o, we will add one more filter. And in the footer will horizontal like user roles. Each row. And here we are going to have a name. So let's see if folks, okay, so we said that the new user that we've just created, those given a student show and the first user propose given an admin role still in the console. So we just managed to assign and default role than a usable created. Now they're going to make this a bit more advanced. So they'll make the code look like this. Basically. I'll explain it now. So basically, if the very first user was created in the application, he will be an admin. So if you create an application and does not know whether that yet you'll build an admin. Otherwise the admin role can be added, overthrow the console as well. The user will be a teacher and the student. Otherwise, each user is created will be a teacher and the student, so that anybody who logs in can both view courses and create courses. That's how it's going to be. Now we can try credit and been more user sign-up. Let's make Example two. Okay, now we are going to all console on small to confirm our email. So confirm. Confirm. They've locked in and let's see, all our users have visited. The new user was given to roles as students and the teacher role. Now let's just make it look a bit butter. So badge, badge in form. Just like this. So in this lesson, we learned how to add roles to users using the qualifier. 34. gem rolify edit user roles: So now we have default roles assigned to users when they sign up. And now they're going to make it so that we can edit the user roles. For this, we're going to go to our users controller. So far as this controller, we go to controllers, uses controller and create. A new action is going to be edit, edit. And, and we are going to set our user. So it's going to be user, user find params ID. Okay? Now they're going to our roots. And here we are going to make it not only index but only added also. Okay, now let's create the views. So they're going to users and they are going to create and edit view. And in that we are going to add a form for editing our roles. And in the edit, the fifth created, we're going to add some code like this. So we are going to create a form for user where they are going to have a list of all the roles and you'll be able to submit. So it's going to look somewhat like this. Okay, we've still got an error. There is no users path for this. We're going to create a new route. So show. And actually we're going to need also update. So we said that the user is an admin. Now let's actually also show the current user. So user in mail. And hopefully we'll have something like editing. Roles fall. And we are going to put it in the called so-called called Herder, called body and called photon. So this is going to be in the Hadoop. This is going to be in the body, and this'll be in the footer. Okay, looks a bit butter. So let's try giving him a student show. The update action can't be fined. They're going back to the user's controller update. And, and here we're going to have something like this, something like this. So we're going to take the current user and update him that the user params and they're going to do redirect him to the users. And you'll have such notice. Otherwise, if something doesn't work, they're going to render the edit action. And we'll also need to add the user operands. So we'll add a private method, the bandwidth for usual health for all our controllers in our scaffold. So we are going to set the user and we are going to have user params. And here we are only going to vote for droll, so it's going to look like this. And we are also going to not have this separate user find params ID here. So they're going to make a before action. So a before action to set the user for edit or update. Now let's try once again. Okay, we've added the admin and student, both to the user. Now let's also add an edge patrols button. So we go to our user and we'll have a link to edit shoals. And it will be added user off. For this user. Let's see how it looks now let's add some claws. Okay? So we opened this user, we open the other user. Let's make him only a teacher. So this Example two is going to be only a teacher. Ok, it worked. Now I see that this notification doesn't work correctly. Let's see Vine. Well actually, nevermind. So user roles successfully updated. Okay, so now we can also edit the roles for all the users. So when we create an application through roles will be created and admin as students and teacher, the first user is going to have our user_data Barbie. The first user is going to have an admin of teacher and students show an issue. Next user that is created is going to have a student and a teacher role as well. They can edit the roles of the users. That's basically how the role of phi Jim evokes in an ideal environment. 35. gem rolify using role based access: So we've added the role of IgM and we have a few users with different roles. And now let's see how we can actually restrict the actions dependent on the roles. So for example, they have our navigation and the silane navigation if it is the current user. But we can add some additional Like if currentUser and current user has role admin. Okay, I must put a question mark here for it to broker. Role of phi clauses suggests us. And you see that we don't see the navigation because we are logged in as this example to user and we cannot, we are not the admin. But if you make it deeper, then we will see it. Now they're going to remove this here. And they're going to try it started not only in a view but in a controller. So here we have our course's controller, the index action, and we want to make it sorted on the admin users consider courses. So for this we will add some validation like if currentUser has role admin, It will be displayed. Otherwise. Redirect to root path alert. You don't have access. And, and now let's try going to the courses. So whenever the user who is not an element that goes to the course list, you will not be able to see it. That's an example of how role-based the actions can be restricted. Now they're not going to use this here, so we will remove it. And let's have a look once again at our role model and the way editorials looks. So in the role model is nice for us to add some validation, really basic validation. So a role has a name and the name has to be present, and it should be also unique. 36. gem pundit installation and example usecase: So we've installed device so that users can create accounts rolling phi so that we can Grunt uses different roles. And now we're going to install bundler that Phil drunk role-based authorization for the use of two different parts of the application. Let's see how the jumbo folks, we will install it. Run bundle. Next we are going to include this into our application controller. And we are going to install on its or rails generate bundle install. So we see that it created a new folder, boluses in our application, and it generated a file application policy. Let's have a look at it. So here is our application policy, and here began at application file, the application vide authorizations. Now we're going to add this part of code so that if a user can't access some part of the application, he'll get an aromatic such that he is not authorized to perform an action. They're going to cope with this. You go to our application controller and add this here. So I double, I have this double, I delete this and this will go to the bottom. Okay? So let's try. I didn't bonded to our application. So we are going to generate a bounded policy. For course. Let's go to our terminal. So generate undid policy, cause. This will create a file in our policies. Postpone course, post.rb. Here it is. And here we're going to add our policies for different actions with the course. Now let's clean up all the open tabs. I'm going to close the ones that are not using consult. So CORS policy, okay, so let's create a policy for added, for example. So let's see how it looks in our application controller. Deaf edit, question mark. And they are going to add the edit for current user has role admin. So here in the application possibility have an initializer for funding the current user and the current record. And we are going to write user has row admin. And now we are going to our course controller. And in the edit action we are going to authorize this course. So now we will start the server and see if it is token. Now, not trail generate rails server. We are on our server. Let's go to causes. We don't have any causes. Let's create fun. And okay, let's try editing. So we cannot allow this course because we are not to the admin user one scan. And this user is only a teacher. What can add him and admin role. And they go back to the causes. And he can added discourse. 37. gem pundit authorization for courses: Okay, so now we have courses and have a course policy, but now we want to make it actually work for each action we have. So for updating, for creating a course, for deleting a course. Now, they have it already broken for editing. We're going to do the same for each other action. So for edit, for update, for new create and destroy. And they're not going to create a poster for older courses because everybody will be able to browse the whole list of courses. And for showing the course, anybody can look at the cost at this moment. Okay? And we're going to add this authorization in our course controller. So authorize costs for edit from you for create, simply that you put it under the place where we defined the course. So update, Destroy. Ok. Now, how do we actually wanted this validation to look? So a user has to be either an admin or the user has to own this record. So the course has to have a user ID. So in the application policy, we define that the record is the record that we've got here. So the cost will be at traveled. This is the course. Record user ID equals user ID. Or we can make it trickled user equals user. So on the admin or owner can edit. Same that update. Then who can create a new course, somebody who has that teacher role, send that create and destroying either an admin or the owner of the course. So let's run the southern safe with folks. So our, our current user is an admin and the teacher, let's say that he is not a teacher listing the stroller vein. And we want to add a new course. We cannot do this. 38. gem pundit only admin can edit other users: Okay, so now we have a user and we'll edit his roles. So we can do anything with editing anybody's roles. We can make anybody and admin or not an admin. And it's totally wrong as well. We can take all the rolls away from a user for the needs of the current application that we're building van going to make it so that a user can not, not have any role. So a user has to have at least Fund's role. For this, we're going to add the following validation code in user RB. So we're going to validate on the update action that the user must have a role. How does this code look so easy? Use it doesn't have any roles on the update action. There is going to be an error that the user must have at least fungi. Oh, let's see how it works. So we go to this user, we update and now the Gund update the user unless he has roll IT folks. Next, we are going to make it so that a user that is not an admin cannot change antibodies roles. Now let's make the current user and admin. And for this we're going to use for making it so that only admins can edit other people's roles where again going to use bundle. So they are going to generate a new policy on the policy for user. Okay, so here's our new policy. And here we are going to add some code similar to the one that we had in courses. So for that edit and update actions, we are going to see too that the user is an admin. Okay? And now we are going to the user's controller and we are going to authorize user in the update and the edit action. Now let's try. So the current user is an admin and he can edit antibodies roles. Let's see. You can make somebody else an admin. He can't take all the rolls away from another user. Let's see how it works and make it so that a user has to be an admin as it's a totally different role that they are going to validate in the user's policy. So become added roles because a user must have an admin role to be able to edit. That's how easily become a permit or not give access for different actions. So far application, we're going to make it sorted on admin users can edit other users roles. 39. gem pundit user can see links only to allowed actions: So now we have a user logged in. It is Justin. He's a teacher and the student, so he cannot edit, enable these roles because in the USA policy it is stated that only an admin can edit other users roles. But we still see at the bottom two electrodes as well. You have two courses created. One was created by Yushin and the other one that was created by example. So the user can edit the cause that he created. He can also deleted, but he can not. At the cost that somebody else created, N3 cannot deleted either. But maybe they don't want to show the user buttons that he cannot press. So we're going to add it in our views. So we'll add something like this. That's going to be such a method. It's also funded method that if policy goals added done, this link will be displayed. So let's see. Okay, a user cannot see the link because he cannot add this record. Now we're not going to have this show link visible at all because a user will be able to open a course by pressing the course title. So you can still do it. The GOP pressed the delete button for the cost that somebody else created that we are also going to add a policy validation here. So of course, destroy. And then he can see it. This way. A user can see only the buttons for action with courses that he created. Now we don't from the syllabus footer. So we're going to do something like this. If both recalls added, done, this folder is visible. And we're not going to use this dough validations. So we're going to comment them and leave them just for reference. Let's see it folks. And we're also going to add the button to editorials visible only if the user is an admin. So they're going to our user. And we are going to add a similar policy. So if policy user edit, and then that'll be this editorials button. 40. gem friendly id for users, user show: So now we have our users and they're going to make it so that we can see the users profiles. So they'll be able to click on a user and see his own base. For this. They're going back to the user uses controller. And they're going to create a show action as well. We're going to set the user for the show action. So here we are creating a show view. And in our routes, we're also going to add the show available. Okay, so is already available. So they are going to add a link. They are going to our user called. And here we'll add a link, link, two user, email, user, user. Let's see how it works. So here we can see the personal a page, a user, but it's empty. And let's just add the code that we've got. So they're going to run the code. Let's take the show until Shonda users, user. Let's see how it works. There is no such arrival, so they must add user, user. Let's try once again. Or maybe vice wilson. Yeah, it works. So don't depress. A user will go to his personal Beijing. But we still see that the values and ideas, instead of a friendly IDs in our users, we are going to change that. So they're going to our user model and we're going to modals user are beam. Let's see how we made it for courses. How we edit friendly ID. So extended friendly ID. And here we are going to also add friendly ID somewhere lower. And I shall go on to be a friendly ID by email. So they're going to undefined method slug. Yeah, because we need to migrate the slugs to users. So the way we did for courses, let's see how we did it. There's our database. So migrations have added just fields and have added slog to causes. We are going to do the same for our users. So I opened the recommendation of friendly ID, Vagrant, make immigration at slog to users. Here it is. Let's fish the things developed using off. Okay, rake db migrate. Migrated. Here is our user. So let's refresh our users and to save all our users so that views the frontal ID. They're also going to our users controller. So users controller. And we are going to find by friendlier ID. So friendly dot find like this. And we are going to go to the console and find each user and save. So it looks now and they're going to the console. So Rails console, Soviet added friendly to users. Let's refresh once again. And we see that we have the user with the slug as his email. So we go to another user and we see his email is as his address in the application. Looks cold. 41. check if user is online: So now we have a few users. And let's imagine that we want to make a functionality to see which users are currently online. So to do this, we're going to update their updated at column in the user. Whenever a user does something in the application. For this, we're going to our application controller. And here we are going to add an after action. And after action and after action is going to be, is going to be called user activity. And we're going to create a method for it. So here we are going to private and we are going to create a method user activity. So there'll be an after action to touch the current user. Now we are going to our user dot RB. And here we'll also add something like this. So they're going to check if the user is online. If the user updated at column was changed less than ten minutes ago than he is online. Let's make it actually two minutes ago. Okay. And I will make it as visible in our views. So they're going to a user called and we are going to add something like user online. Yes or no. So we see that now the user is online at the moment. Oh, actually, the user that is currently locked in is online. So true, it works. Now let's log in as another user. Okay, and we get an error. And we get this error because we want to see the course while they are not logged in to access a policy without having a current user. So let's make this visible only if the actions visible only if the current user is logged in. So let's also go to our dog goes cold calls. And we're going to check for disposed only if currentUser like this. Let's check if it works. So now it folks. And let's look in the other user. Okay, so we've looked in as this other user, and we said that he's online. Now, let's make a list online tin look a bit better. So it will be something like this. If user online. Font, Awesome from the eyes Font Awesome, circle. Okay, and let's make the circle have another color. So tax success, it will be green. So it is green. Let's also make it on the beginning. Like this. We can also change the way the so-called looks. And if the user isn't online than it will be another kind of circles. So else texts, danger. So it's going to be rather so this uses are applying and this uses online. And remember an integral, this user was locked in and he was aligned, but now he's logged out and he hasn't performed and actions for over two Mendelson. So he is offline. 42. add a Lessons table, friendly id, design id: Okay, it's time to add some functionality to our application, but let's have a look at what we've got. So we have users and uses concrete causes. Causes belonged to users as well to have roles. So we have row names and user_roles. Enroll names who have admin, teacher and the student. And user roles connect users and roles. So a user can have a few roles at the same time as the bell for the public activity jump. We have activities for the friendly ID, jumbo, tron lady slugs. So in activities via all the track of all the actions that the baton in the application he has the activity example that the course was created, destroyed. Or they'll also have edit actions here and inaction tax rich texts. Here the goal to create course and the information on the rich text editing is kept in this table. Now we'll add some functionality and they'll started at in the add-in lessons to causes. So let's create a scaffold of lessons with a title, with content and with blown into a course. Let's go to our application rails generate. Scaffold is going to be called Lessons title. We don't have to say string because it's stringer by default. So content, text and the course references. Let's see how the migration looks. We're going to the beam migrate. So we create lessons with title content and references. Dog goes, OK, let's make the migration, rake db migrate. Ok, we've migrated. And now let's go to our modal and set it up. So we are going to modals, goes, belongs to user and has many lessons. Lesson belongs to cause. Okay? Now though at some validation, so validates title content and calls. In the lesson as well. We will add that premolar ID gem right away. So we're going to add the extent friendly ID and habits fifth title. Okay, so we need to also run the migration for a slog to our lesson. So let's go to frontline documentation and we'll see how to add the slug once again. So at slug, at slog to lessons. Rake, db migrate. So migrated. And actually, when we have a course that has many lessons, we are also going to add some action like dependent, dependent destroy. So if a course that has a few lessons is destroyed, the lessons are also destroyed. Now let's have a look at our lessons in ovules. Let's start the server. Okay, so here we can have a list of all our lessons. Here's an example of a form. Now let's create a sample lesson. So first, content, whatever, and the course will be, let's say my course. Ok, we can find a lesson with a default because we didn't finish installing parental ID. Let's go to lessons controller and add the lesson proudly dot find. So let's save it and visited lesson was saved and the helper, the friendly portal. Okay. Now let's make it a soda to them via open a course, you see the lessons that belong to the course and as well as ad hominem lessons of course has in the course views. So we'll go to the course code, goes HTML. And somewhere here we are going to add the Venmo, God footer and FA, FA MOOC and goals. Doubtless suns dot count. So this way we are going to count how many lessons that goes has, and this is a discourse has, one lesson. So when we opened the coastal, Want to See this lesson in the course? Let's make it also visible. So for this, we are going to, our courses show, and here we're going to add some code to render their lessons that bone to this course. So first we'll go to the courses controller. First, our courses controller, here it is. And here in show we are going to have lessons, are goals dot lessons. Okay, now let's run the veil lessons. But before we run that the lessons, we need to have a view of the lessons that we are actually going to render. So let's create a lesson review, lesson, HTML, humble. And inside it we are going to have, let's see, which we'll have in lessons. So in less than HTML HML, we are going to have the title, the content, and the course, and the show edit and destroy actions. So you'll create a card. In the card we are going to have a header. And we're going to have a header for the title, a body with the content. So header body here will have less sun title here we're going to have lesson content. Will also add the course information just in case Lesson calls and will have the links. Let's copy the links in the footer. Okay, we'll have the links right here. And let's render these lessons in our ghost show. So they're going to render lessons less sun. And let's think, oh, we'll first need to have a collection of the lessons like this. So less than each do lesson and gender lessons where a lesson is less than. Let's try with folks. Okay, so we have our lessons rounded. Now let's make it look a bit better. So in the sidebar, they're going to have the course. And in half of the screen is going to be the course information and half of the screen is going to be the lessons of the course. So let's create a column. So critical in the crater. Oh, so column large six. And calm logistics will move forward. So calls and lessons. Okay, so here we have the course information. Here we're going to have the lessons that belonged to this course. Now let's also added these, these actions for them to look a bit better. So they'll be no linked to show here is going to be in the lesson title. So they'll have the lesson title instead of show here. Okay? So we press the title and V, c, C lesson now will also added some clauses here. They'll just copy down from our course. So to edit from there will be born in bottom. And to delete there will be a danger bottom. Let's see how it looks. Ok. So we have a list of courses, VC, How many lessons a cause has. We can see a course when we opened the course. And if a course has adolescents will see the lessons that the Cole's house. So we open a course that has Ellison and we see the lessons that the course has. Let's try opening a lesson and they have an Edit and back action. Let's, instead of this show information, also run the code lesson called the lessons show. So we are going to lesson show first, we'll delete these files that found going to use that JBuilder one's lesson show. And same as we did with the course show. They're going to run the lessons. So here we are going to have run the lessons. Lesson. Lesson is less than the total explicit. Okay, have you seen our lesson and the back action will lead us back to our course. So it'll be goals of lesson course. Now, defined local variable lesson because it should be within at ok. We press back it folks. Let's make it back to cause. Okay? So in this lesson be graded and UI, table of lessons that belongs to causes. A lesson has a title, has content and belongs_to calls. We can see the lessons that belong to a course and you can edit them. 43. public activity for Lessons, create lessons inside courses: Now to add public activity, jump to our lessons million that the banana we create or update or delete a lesson. We'll also have activities for it saved via just going to add some go like this. So there, including the public activity modal, same as we did with the course. And we are going to add this depth two s So that the goal of the course, we're going to see the ID and the name of the course, but not an active record the piece of code. Now, to see it probably will restart the server. Okay, so here we see the public activity for the lessons also. Now they're going to make it so that V create lessons inside of courses, but not another vein. So for this, we are going to go to our course show. And here we're going to add a bottom like link to add less sun. New lesson. Ok, so then we open a course VC, this button to add lessened and did like the coast will be automatically populated. And they're going to pass the current goals ideas. So the course ID is going to the course ID. Okay, and now we are going to all lessons form. And here we are also going to pass the course ID. So in the lesson form, we're going to add some code like this. Basically, we are sending the course id as a parameter in our controller. So we are creating a lesson knew with a course id three, and we want to see this ID3 also set here. So we are going to remove this as thin, and instead we're going to input costs idea. And the value is going to be either the course ID that was already assigned to the lesson or the course ID that we have in our params right here. And they're going to have it as hidden. If you don't have it hidden, it's going to look like this. But we haven't had hidden, it's going to look like this. So let's add a lesson with params. Ok, we've created this lesson and it already belongs_to calls. So let's try to create an adolescent with another goals. So I didn't lesson, lesson with params. And this lesson belongs to our second course. As you see. 44. action text for Lessons, add breadcrumbs for lesson show: Now they're also going to add action text in our lessons, meaning that we'll have such kind of rich text editing when we add a new lesson. So we're just going to copy it from our post.rb. Post.rb. We have has reached text description and in less sun dot RB, They're going to have has reached text content. Okay? And how do we have it in the goals foam cores? Form. Html. Okay, goes form. We have rich text area and label for description. And in our lessons form we're also going to have the same but for our content field. Ok, so that's the most simple way to add the our rich text area. And let's hide the field that they're not going to use. And let's try adding something. So with rich content, Let's save. So it works. What we see that we have do notifications, we are going to our lessons show and they're going to delete this notice that we don't need anymore because we have a centralized fall who'll application. So whenever we edit or delete a lesson and they wanted me getting this duplicated notification animal. Let's also add breadcrumbs to see which goes via in. So then we were creating courses. We also added breadcrumbs like this. And we'll add similar breadcrumbs for our lessons. So let's see. They're going to have a buff to all the courses. We're going to have a buffer to the lesson dot coastal title, lesson dot chords dot title. Let's see how it looks. And it will have the name of this lesson. So linked to lessen, not title. And it's going to be lessened both for this current lesson. So here we've also added breadcrumbs for no less than that we had. Let's go to a lesson and Florida, but bread crumbs. We can edit the lesson. We can edit, give us some nice rich text content like this, and it's going to be there. That's it for this lesson. 45. gem pundit authorization for Lessons: Next we are going to create an authorization policy for our lessons and they're again going to use the pundit gem. So we are going to our policies, let's find them. Here are our policies. We're going to create a new file. We're going to name it user. No lesson. All is c dot RB. We're going to copy what they have in our coasts policy. Paste it here. And now let's think, oh, can edit a lesson. Either a user who is an admin or the owner and chill, let's make it so that only the owner of the goals division lesson belongs can edit this lesson. So if a user created the lesson and created the course, he can edit the awesome. Okay, so Record dot, dot user ID is current user ID. Same with date. Same with you, I guess. No, actually, we're not going to do anything for the new and create actions at the moment. And for destroying. Also, although the user that credit course can destroy the lesson that belongs to this course and they are also going to rename it here. So less sun scene. Looks nice. So now they're going to oppose the edit, update and destroy actions. So they're going to our lessons controller. And they're going to authorize destroyer. Authorize lesson than in update. Also authorized lesson and create in. Additives are also going to authorize Los Angeles cleaned up. Okay, I've cleaned up the commented lines and coming back, they're going to authorize lesson for editing, for updating and deleting. Now let's try once again. So we have v logged in as the example user and we have a course created by Yoshua user. We want to delete a lesson that he created. And we cannot do it because they are not authorized to do it. Let's try to edit it, the conduit either. Now let's also make it visible only if you'll make the buttons visible only if a user can actually perform actions with this lesson. So same as we did with our courses and users. We're going to lessons, lesson and we are going to see how we wrote it for our courses. So if policy, if policy lesson edit or delete, they're going to have the Scott filter. So now I don't have the cod folder because I am not authorized as the example user to edit a course created by the user as well. I notice that we don't have a link to this user in the goals. So they're going to add that. We are going to cause. Here's the course user username. And we're going to add a link, link two cos user, username, user path, cause dot user. Okay? So the added it. Remember that we can see the uses that are online at the moment. And we'll also add some space between the codes. So we are going to lessen and they're going to add a paragraph so that there is at least some space. Now coming back to the most precious part of creating a course, it's the content. So we will want in the end that only uses who bought the goals, admins and creators of the course to be able to see the content of course. So we're going to add an additional policy for the lesson show. They're going to lessons policy and we are going to create a method for show. And here we are going to have either the owner of the lesson and the cause or a user who has a row admin. See the course. And in the future we are going to add additional functionality for users to be able to buy the course and uses the battle by the Coastal. Also see the content mode. For now. We are going to make disposal Voc, they're going to our lessons controller. And for our show action, we're also going to add the authorized method. So we are example user. We're looking at the course credit by Yoshua. Let's try opening a lesson that we can not do that. Let's also hide the content here. So we're going to listen. And if God, if both the lesson show I've done, the user will be able to see the content. Now, exemple user is not an admin. He is not the creator of the coastal. He cannot see the contents of this lesson. If he goes to his own calls, heroes, his own course. And then he will come and then he should see what he doesn't but doesn't he? Because he's logged in as example and not as example two, this is a course created by example to. So let's create a course on our own. So example, cause whatever. Let's create a course. Let's add a lesson. There is some content. Let's make it rich. With added it. We are going to the course and we can see the course content. That's it for this lesson. 46. nested resources: Now, when we create a new lesson that looks like this lessons and lesson for whatever the name is. And as they'll be helpful both to see all lessons and we definitely don't want to have that. So we're going to nest lessons inside courses, meaning the path will look something like cause example, slush lessons slash lesson bomb. To do this, we're going to nest lesson roots inside Coast roots. It's going to look like this. So they're nesting them like this. And ok, and this is going to break our application by, because before we had the paths like lessons path, new lesson path, and it's going to look like new costless and path added cost less than path goes lessons powerful, sold. Let's make it actually work. Let's go to our courses. And let's open a course. So the first arrow that we encounter is the new lesson path in the courses show. Let's open courses show. And it's going to be new course lesson puff. And they're going to set the current course. And we are going to set a lesson. So course and lesson. Okay, next era, lessons, slush lesson. We go to lesson and we see that there is no such link to lesson is going to be goals. Lesson off. And this is going to be lesson. Let's try. Okay, next for the edit and destroy actions. So also it's going to be at the goals less than buff. And for delete is going to be cause and lesson. Let's see if it works. It works. Now let's try opening a lesson and we see that we have an URL, so confined a lesson with friendly ideal example. Let's add our current costs to our lessons controller. So we are going here and we're going to set our course. So we're going to need to add the search for that course, params in the controller. So here we are looking for the gap grading NU goes less than the current cost and current lesson. And we are setting the current cost and there's a current lesson. So we are finding their goals and their lesson right here we have courses, example and lesson you. Okay? And now we have an arrow that there is no method lessons path in the lessons form. So we are going to the lessons form and they're going to change it here. So we are going to also set the course. Just like this. Let's refresh. Okay, we still get this arrow. And they'll need to actually set the course in the new and create actions of that lesson because we set them in the show edit, update, destroy, but you don't send them into new. So here we are going to also set the course in you and v are going to set the course in great action. Let's see. Okay, it worked. We have a new era. So less than, you know, link tobacco, really simple. The go-to lessons new and they're going to cause off course. Okay? So we can create a new calls inside the new lesson inside the course with such, such an oral so nested lesson. Let's name it like this. And depressed crate. Navigate around. Let's see our error in our controller. I think I know what the error is. So then we'll go to the form. Let's make this association cause visible. And we see that we don't set a course here. Now we're not going to use either the input or the association. Instead, we're going to set the course, the concrete action. So here we're going to assign a cost than to create a lesson. Let's try now once again. Okay, we managed to create the lesson, but the redirect tool doesn't work. So they're going back to our lessons and they're going to redirect to cause dot lesson. Now this doesn't work either. So we'll make this even more explicit like this. So cost less than path and we'll do the same for our update action. So refresh. Ok, it worked, but here is our next era. Lessons show. No path. So they're going to lessons show. And the program was on line five. So you should be course lesson at course and Atlas and okay, finally developed. Now let's try opening a lesson. Okay, here is the error. Let's see vine. Because here in this link rosette and only the lesson, but we're not certain the course. So usually also set the course. Novel, go back and try open the lesson once again. It felt lucky us. So in this lesson we've had some really complex usage of Ruby on Rails and nest in the resource inside another NVivo, fixing all the links so that they were OK. Now let's try just for the experiment. Okay, here are some more things that don't fit. Ok? Let's see. So yes here versus an owner the lesson, but we are not set in the course. As you see, there can be lots of underwater icebergs had been working with this. Okay, and they're going to the lessons added. And they are going to have some changes here. So back little bit to cause both less sun dot cause and shoudl be there'll be actually know Malia, devil Belt, show action, so cause less son off at calls. That lesson. Okay, it felt if we can edit the lesson, edited, update, it felt, let's try editor once again and see the other actions, show and back Voc. Let just rename it like back to calls and show us some. Okay, IT folks. So in this lesson, we learned how to nest of Andhra source on the another and make all the links and all the routes and actions work. Thank you. 47. gem pundit authorization for Lessons create action: Now concreting up and it poses for our lessons, the left one security a thread behind could not create a policy for the new and create actions. Meaning that a user who isn't the owner of a course can create new lessons for this course. We're going to work on this now. So first of all, they're going to add this same line in our create action. Meaning only the owner of the course to visual lesson belongs can create this course. And they're going to our lessons controller. Here. We are also going to add authorization for our create action. Let's try now. They're going to our courses. They're going to cause that doesn't belong to this user. And we are going to try to add a lesson. Okay? Now become do it because the policy is invoke. So if you go to our console, we will see that the go_to block on lessons policy RB in the create action. So here's our create action that we've just created. And it redirected the user to the previous page, lessons NEW. Now, in the lessons new, let's go to a course that our user created Soviet. It is Bij mirror off. Let's find a lesson. In the course. We want to create a lesson, but we don't get an error message four, no content. So we're going to add it. Now as far as I remember, we've already added a custom error message like this for our form in courses. So we're going to do the same for lessons. So here we are also going to add such error and we're going to use the content data field. Let's try once again, ok, now they're getting there same error message as we wanted. And let's go back to our lessons controller. And here I see that the v also did not assign an redirect to our destroy action. So for example, if we go to our Coursera course and we see our lessons, if we destroy a lesson, they are going to get an error because we are trying to redirect to a lessons that doesn't exist anymore. So they're going to try to redirect to the course lesson. Let's try it once again. We are saving and Christendom. Okay? Okay, we have this around because they're directed to a path of the actual lesson that we just deleted. Instead, they're going to redirect to the goals to which does less than used to belong. So let's try once again. Okay. Now I'll go back to the goals. And let's see. So the record was deleted, but it gave us that redirect message error. Let's try once again. Ok, this time deleting a record vocal, and as of now it's going to work properly. Now, here is the most security threats via vitalist and the costs. Meaning that it is possible for a hacker to create lesson, but the title and the content to, and of course, if he knows the ID. So they are going to just not whitelist this course ID because very suddenly in our create action right here. Now let's try creating a course, a lesson. Ok, so you've seen the still concrete. Our lessons though we don't have the course ID waitlisted in Lesson params. 48. minor styling for edit and new views: Novel omega, the lesson views also look a bit better, the same as we have in course. So in courts have called for new and a god for edit. We're going to do the same for our lessons. So in edit, we're going to have a code like this. Then we have a God body for the form. And for the footer. We don't actually have anything for the footer now, but we're going to put all the links into the photos. So it's going to be called footer. And here we'll have our links. Let's go to the style to the other edit action called footer and put the links Same for the new action. So here we'll have a footer and linked back and new and the new action for lessons. Also create a code. So God header called modeling and called filter. Let's see. Okay, now creating lessons or editing done the look a bit more printIn. Let's go to that adolescent link. Okay, it folks, nice. Let's just make it go to back to course so that we know where they're going. Okay, until also at the bottom for this lesson. So they're going to causes show and for the adolescent or at the bottom clause, bottom, bottom, primary, bottom, small. And we'll add some space. So we'll put a paragraph. Okay? And we'll make it very big button drivel at that bottom block. Class. Not that bad as well. We will delete some views that we are not using. So our scaffold generated lessons in this philosophy are not going to use it. 49. production tour around heroku: Now I'm going to show you a little bit of Heruko functionality. And so here is a list of all the apps that I have run in. And they're going to go to the ablative head relevant. Now Korsakoff's. So here we see all the atoms that I installed. Let, let's see what we have in resources. And these are our add-ons done in deploying. They have an interesting thing. So Deliver deployment method GitHub, and we are going to connect our GitHub to Heroku. So course sago, let's search for it. We found and we are connecting API rate limit exceeded. Ok. So it works for us and we are going to enable automatic deploys. So now whenever we push our changes to GitHub, changes will automatically appear on Heroku. Now, in metrics, we can see how our app is performing. If we're using a paid version of Heroku activity, everything that they've done, like each time we push to Heroku access, you can add other people who will be able to make changes in your repository, like pushing comments, for example, incidents. You'll be able to rename the obligation, add custom domain, or delete your application. And here's another thing that you can do. You can go to data. So we're taking our core Saigon. And here is our database. So we see that 25 rows in our application have been filled. And if I go to durability, they'll be able to actually make backups of our application. So automatic backups are available on the four paid versions of Heruko. But anytime you wish you can create a manual backup. It will create a copy of all that the database records you have in your application and you'll be able to download it. 50. gem exception notification catch errors in production: So now we are going to install the gem exception notification. This is a jump for receiving emails whenever a user encounters an error in production. So for example, carries our production application and a user goes to some kind of Page and he gets some kind of error like this. There are two ways to check for kind of era was happening. Introduction. Either we can go to our console and run Heroku logs tail and they'll be able to trace the error that happened. Or we can install the gem exception notification and receiver. Each era uses encounter introduction as an email. An email would look somewhat like this. So we will have all the information about the session, about what actually goes to the ARRA. And we'll be able to troubleshoot all the errors that get in our exception. Emails, solars installed the gym. They're going to jam exception notification going to our gem file and bundle. So bundle. Okay, and now we are going to add the skull to our production dot RB. So they're going to config environments for the action dot RB. Okay, reload. And here we will add the scold. Now let's move it up inside. Ok, so these are the details for sending emails. She notification jumps all the notifiable B, it's like a name. So core sago, era. Here we are going to have something like support at coursera dot herokuapp.com. And the recipient is going to be our real email address to which you want to get all those error notifications. So we'll put something like this at Gmail. Okay, looks good. Now let's add this to GitHub commit. And they're going to put this to get home. So we'll put another going to push it to Heroku so that the jump dogs in production. So we've pushed to Heroku and now let's try running the Arab ones gun. So they are refreshing the page. Nothing works. And let's see, we received session email. So I went to my email address and here I see that just now I received an email course ego error by supported Kosovo Heroku app and see the details of this error. We know why it happened. So that's how you use the jump exception notification to get emails about errors in production. 51. design for courses and lessons: Now we are going to work a bit more on styling our application. So first, I remember that when we created the new fuels for device, a device confirmable if we did not add this two seats. So that then bcd, a user, he's already confirmed for having the user confirmed. When we make the seeds, we are going to add such a method instead of the one that we had. So we create a new user. Let it be admin at example.com. The bus vote and puzzle confirmation are going to be the same. And we're going to add to this uses skip confirmation method. So it is going to set the confirmed at a date to the time now and the user will be automatically confirmed. Okay, going back to the application, let's go to our courses. We have a course created. Okay? Now we have a book inside. Let's make it look like asks, like checkmarks. So let's go to our Font. Awesome. And let's select dot slug tasks. Okay, we see such such tasks icon. Let's go to our goals. And here in the course, HTML, we're going to add, instead of book, we are going to other tasks. Okay? Now, then they open the course. We see the same page and we have the ad lesson button. Let's try pressing it. Okay, we have a new lesson. Let's see how we have the new coast looking, okay, now we see that there is no space between the content and within the great lesson. So we are going to our lessons form. And here we are going to add the paragraph. We're going to edit after this rich text area. So it looks a bit better. Now let's try creating a lesson. Okay? And VC, something's wrong. So we don't want to see the course name in the lesson description on the bottom. Let's go to our lesson. Yeah. We had the visible as lesson cause they're going to remove it. We don't need the course, we need only the lesson content visible. Let's actually try making the content look like rich text area. So we will highlight something. Okay, it folks. Now let's add some more science. I mean some more icons. So for a single lesson they're going to use this check square icon. Lets add it here. Font, Awesome Font, Awesome, shock. Okay, and they're going to have such a kind of Chuck's right next to each lesson. Now we can make it look a bit different if we add Font Awesome, regular. So. This icon looks a bit better. Let's try a little bit more lesson. And here we are also going to add this icon. So they're going to cope with the icon. We are going to then UO action. And here we are going to nested under the header. And they're going to have this checks for. Now, I think had the one is too big, let's make it header three. And they are going to do the same for our edit action. Like this and editing lesson. So we create a new lesson. Now we get an error. I wonder why we get this error. Let's see now console. Okay, I'm not sure why we had this error, but when I restarted the server, everything worked fine. And now we're going to our users list. And we don't want to see our users into places as gods and in the table. So we are going to leave on the table of users visible. They're going to our users. They're going to the show action. Okay? And we're going to index, and the index Virgil's going to hide our cod columns. So comment, comment, comment. Okay? And they are going to use only the table. Bottled. Want to also have some of the information that we had in the calleds and don't have in the table visible in the table. So they're going to user, they're going to see this confirmed email method here in our table. Let's go it. So we create a new table header will be confirmed. And they're going to add a table description. Let's save with folks. Okay, we said that the user is confirmed And what does it have? Had our roles. So we're going to add the roles also visible in the index. There's going to be a table description. And these fields are going to be nested under this table description. And here we will have roles. So we have the roles. And if the user is an admin, you will also have the patrols button visible. Now let's go back to our views. So here we have our calls. The press the button to adolescent VC, a checkmark, the want to edit a lesson, CHF mock. Now let's do similar things for the course. So we're going to add some more Stalin for this views. Now. We are going to add some icons. So they go to cause new. And let's see how we styled our lessons added for example. Okay, so we're going to have a, had the three. Next they're going to have a Font Awesome icon. And the icon that we used for our courses before. Bolts, aggregation, cap, and new goals. Let's see how it looks. Okay? And same for editing courses. So we go to courses at it and we will add a similar style. So courses added and they are at in the style. Looks like the button. Now I'd also like to add the breadcrumbs that we created for the course show to our, I mean, for the lessons show to our lesson, edit and lesson you burials. So let's go to our lessons. Show. Here are the breadcrumbs that we created. And we are going to add something similar to the new and edit actions. So we go to our lessons inside the causes, press Add lesson. Here we are going to add some bread crumbs. So new lesson. And we don't have a lesson yet. So here we will have new knowledge. Civil doesn't folk lesson coast title. Yeah, because there is no course created. The Soviet just going to have the current course. Okay? So we have our bread crumbs, we have, all our courses, have this course, and they have then you action. Now we're going to add something similar for edit. So Let's just see how it looks at the moment we press added and everything Burke's Knowledge just add an additional edit sign here. So the C edit, your MVC that we're editing discourse. I mean this lesson. So in this lesson we just did a little bit of styling the added and create the new actions. And that's it for this lesson. 52. gem pagy for pagination: Okay, now we are going to run our seeds. So rails db seed and we get an error. Let's see, because the current user is no class. And where do we want to call our current user? In coasts are BY 27. So cause.org, line 27. Ok. We said that we want to show you the current user, but we don't have a current users up. We're not going to set the current user for the courses that they're great proceeds. And we are not going to have public activity for them. So they're going to disable public activity for our seeds. So enable it in the end of seeds and disabled for running the seeds. Let's run our seeds. Rails the BCD. Okay, it, this time. And now we see that the only good gut the rail six volumes. Now let's restart our server. Here we go. Okay, we see that we have got to how many new go to. It's still starting its repression. Okay, we've got 61 cozy in our database. And we can scroll through all of them. But we don't want to let the user see all our courses on one page. And for this we are going to use the gym Beijing. Let's see the documentation. So JPEG is a new gem for pagination, for having the different pages for our records. And basically, it is a new gem that is more performance than Bill Bennett and the commonality and the guy going to install this jump right now. So here we have our documentation for how to install page. Let's do it with a gem Beijing and added to our gem file. Okay, not the wrong bundle. Now we are not using these commands because we are using Bundler. Next we are going to create a page Adobe file in our config initializers page. It doesn't provide a generator for this, so we are going to do it on our own soul, config initializers. And here we will create beijing, Beijing dot RB. Ok. And inside it we are going to add the contents of this file so that they get as for coping based. And we have it here. Next, let's see what we must do. In our application controller. We are going to include pager backend. So they're going to our controller's ApplicationController. And somewhere here we will add page your backend. Ok. Next we are going to add pages to our course's controller. So they're going to our courses controller. And now you see that our controller is already quite complex because we are using RANSAC and we have to make it look somewhat like this. So they're going to make it to, we're going to have Beijing. Here, we are going to have courses. And here we are going to have this code. Here. We are going to come in this line and we are going to have paging. Let's see if it works. Now going to start our server. So they expect to have our records paginated. Now that we have plenty causes. So it is because page has a default of 2020 items per page. Let's find that here. So there default is 20 items, but we want to change it and we can have for example. But let's say for the first two items of one page, now we will have to restart our server for our initializer to start working again. So noisy that we have just two items per page. Now we are also going to add links to go to the next or previous page. So for this application helper and they're going to include page upfront and now let's clean it up a bit. And good page a front-end. And they're going to include this command alleged. Let's turn it from HTML to HMO, or it is. And we go to our course's index. And here we are going to add paging inside the same code. Let's see how it works. Ok, so we have our pagination. Now let's make a note on the side, but under the cod columns like this. Ok, now we want to make our pagination looker a bit nicer. And let's see what else that page Jim suggests us to do. Now. We're not going to do this stuff, but we're going to search for Bootstrap. So they have a bootstrap extra. And they're going to include this initializer. Open pages. Are they going to add Bootstrap? Let's go to Beijing. I'd be right here. So we're going to uncomment this section with Bootstrap. And next we're going to add page Bootstrap navigation. Let's take these links. Don't then from HTML to humble. And try I didn't owe them at the same time, we will stop the server. We will add these links under our page and off let's say all of them started our server. Ok, so we have three different types of imagination that must vote. We're just going to use the Bootstrap point for our current example. So there's vision days off or comment on this one, and we're left with our bootstrap. Origination. Looks nice. So in this lesson we had a really quick installation of that pg gem that provides a real quick solution for originate in our records. Thank you. 53. add dynamic title to page tabs: Now we see that no matter to what page in our application we go, they still see the same title in our tab and we want to change it. They want to make this title dynamic. So to do this by going to our application HTML, and it's never going to add some code like this. So we're going to have add dynamic title. Let's comment out the old kind of title. And next, next we are going to our views that we want to have our tab name edited for. So we are going to, for example, courts show, and here we're going to add this information. So here we have our name of the app or anything they want. And later we can have any dynamic kind of content for this title. So for example, we are taking the course title. Let's refresh and heavy C causes business financial. Now we're gonna go to courses. We see just all the courses because we don't see any title in courses index. Let's open courses index. And here we are also going to add a dynamic title. So like causes all courses, it's not going to be dynamic here because nothing's going to change on the course's index spatial. Ever. So here we have all courses whenever opened. And of course, we see the name of the course. And it looks kind of nice. They're going to Edit also for users. So they're going to cause you to users index. And here we are going to add some like all users. Also not dynamic. But when we open a user and actually we don't have Linked Open the user here. They're going to add this link. So let's take our user code and here we're just going to cope with link. So linked to use an email. And here we are going to have a link to user email, table description. We're going to delete the user email, okay? And they're also going to get the online buttons visible. So we are going to use and we're going to add this online status will add it under the same today as the email. Oh, okay. Let's see if it works. So to see if a user is on line, good. And we see that, that if you go to this page, we see all users now gonna go to a page of a particular user. We're going to also make it so that he is, his email or his username is visible here. So let's go to our courses show and they're going to cope with the title into our users show called. And here we're going to have title. And here we are going to have at the user dot username. So here we have this user in our title. Now we can add the profile. So we said that it is a profile of this person as an example, but then are going to do it in this application. So now what else do we want to change? We have the homepage and the homepage. We are also going to edit this tab. So they're going to our views home index. And in-home index will add something like like core sago Online Courses. Learn an antenna on your shadow, just some kind of marketing content. Okay, now which other pages that we have? We have a page of activity. So for activity we are also going to add something. Just activity. Okay? And which other pages that we have? We have a page to show a course, Nabi, see the course name. We have a page to create a course. We are going to also add a title for creating a course. So let's go to courses you. And here we're going to add a button. So COS, COS sago knew cause than have a button to edit a course. We can now edit on the courses that belonged to our current users. So let's circles are drawn to this user, okay, of course, sago edit calls. And they go on to our edit action. And here we are going to have so called sago, then added. And the course title equals at course title. Oh, okay. So editing, editing this course. Fantastic. Now let's see which other views we want to add the title fall. So edited it for the course, Edit, index new and show actions. Home activity and index. Lessons. Lessons were not edited yet. So let's go and see our lessons. So let's open a lesson. Let's go back to this course. It was a course, yes. So they are looking at the course. We are opening a lesson and we're going to add the lesson name in the title and the course also. So we are going to have coarse equals at course title and lesson equals Atlas some title. Let's see. Okay. Now we're going to add some slashes for all navigation. Soviet have our navigation on top here. Looks nice As for me. And we're going to add the lesson additive in a similar vein. So they're going to lessons added. And we're also going to add a title here. So let's see how it looks, OK. And we're going to add developed editing editing lesson. Okay? And let's go back to the course and at the title for adding a new lesson to an existing course. So let's go to lessons New. And here we are going to add a title. So we don't have this lesson created yet. That's why we don't have at lesson. And we're going to add something like new lesson. Okay, so that's it with the, our titles for this lesson. Now that we have all this beautiful dynamic titles wherever they go in our application. Thank you. 54. scaffold Enrollments: So now they're going to add a new migration of Angelman's uses can enroll to causes and uses that have enrolled. Course can leave a rating and write a review for this course as well. Owners of the course. So the people that created a course cannot enroll to their own courses. And there'll be two kinds of courses, three courses and paid courses. People will be able to enroll by clicking Enroll button to a course that is free. Otherwise there will be suggested to make a payment to enroll to a paid goals. So now let's create the migration. They're going to our console. And let's write rails. Generate scaffold is going to be enrollments. So calls user rating and review, rating integer. Ands review will be taxed as.val, and we'll add an additional column that will be price, price integer to see at what particular price the user bought this course. Because that cost price can be dynamic. So they'll know at what particular moment of time price the user bought the calls. So we're going to also add it here for us not to forget. So price integer. And now they're going to run our scaffold. In the meantime, I'll clean up the files handled using at the moment. Okay. Now first of all, they're going to our modals and they're going to add our enrollment style course and user. So of course, has money and Joel nuns. Same that user has many enrollments, has many causes and has many enrollments, will put their relationship someday somewhere higher. Alkane. Next we are going to our newly-created modal of an enrollment. And let's see what we have here. So the enrollment belongs_to goals and belongs_to user. Now they're also going to add some validation. So that cannot be an enrollment that doesn't belong to a course and a user. Next, they're going to add such kind of validation. So they're going to vote at the uniqueness of user IDs, scope course id, and justness of course ID, scope user ID. This will not let us great combination of ghost user device so that a user can not be enrolled to the same code twice. And the courts cannot have the same user enrolled device. And they're also going to add one more kind of validation. So a user who created the course cannot subscribe to the schools. It will look like this. So if they are creating a new enrollment and the user ID in this enrollment is the same as the US AID that created the course. We're going to get an error. Now, I consider validation is really important to make the Grails application work properly. Now, they're going to make a list of our subscriptions visible in our header. So they're going to our views. Layouts harder and have, are going to have a list of all our subscriptions. So link to enrollments. Enrollments. And how is our icon go into look. Let's go to Font. Awesome. So logically, if of course, if a user is enrolled her cost, the cost is unlocked for him. So we'll use the lock open sign. So FA lock open. Okay. And we're going to go to that subscription, some enrollments path. And here also enrollments path. Let's have a look how it looks. Ok, we have a list of our enrollments. Now let's try creating an enrollment. So they go to new enrollment, they're going to select a random calls. And we are going to slug the current user. And the rounded at the current user was the one who created this course. Let's create an enrollment. And we get this error that we cannot subscribe to our own course. Okay, so one of our validations definitely evokes this one. You cannot subscribe to your own course. Okay, let's make the other user subscribes the schools. Let's see if it folks. Okay, it felt now let's make that student example.com user subscribe to this course, Vice. So we're going to enrollments where they can the student, I've got taken this biological science and we seen that he cannot subscribe to this course. Once again. Now let's make him subscribe to another goals. And you see that it works. Now, we'll validate whether this validation works. So they are trying to create a new cause without anything. And of course it doesn't work. And we get an additional error because we are looking for a US AID that wasn't provided. So they had an errata and added, added this additional if statement to check if the actual have a user ID. So now we're looking at our enrollment form and we see that we have a price column. Now, nobody is going to input the price. It's going to be automatically copied from the price of the calls that was at this moment of time. So they are going to go to our views in our enrollments. Now we'll delete the views that are not going to use. So the JSON, JBuilder ones. And in our phone they're going to remove the price inputField. Next we are going into our controllers and gentleman's controller. And here we are going to remove the price so that nobody can input the price manually. Also, I will clean up the common things for the controller to be a bit cleaner. And here in the create action, we're going to add some code to cope with the price of the course. So it's going to be enrollment dot price equals enrollment dot cause not price. Okay? Now we're going to check if a barracks, they're going to our enrollments. We're going to delete the ones that we created and credit. And a gentleman from the beginning, Soviet taken a random cause. We had taken a user and credit and the enrollment and visit that the price was automatically populated based on the price of this course. Now, let's make that Angelman stable, Look at the butter and enroll in a stable and all the views. So we have our edit and they're going to see how we start our edit action for courses. So here we had the title. They're going to add a title to edit enrollments also. So editing and enrollment. And in the Angelman RB, we're going to add to S method so that the boundary just call the Angelman, denote what VOT actual day-to-day colon. So death's door as. And here we are going to have a user and cause. Let's see how it works. So they're going to Edit action. Now obviously that we are calling a protected method. So they're going to make it not protected. They are going to move this to us out of the protected methods. And it will place it somewhere here. So we're going to refresh. And here we have edited student at example.com. And we're also going to add the course name. Now we get an error because we cannot have plus with an unknown format. So we're going to make the format string to us and to us. Ok, let's see. So it works. Well. Let's have a look once again, and we'll add some space in between them. So we're going to add 10 plus. And here we are going to add some pretty space like this. So now we are going to put it into our code. We're going to our edit action. And here we're going to add a called lock open. And then God, body. Inside. We are going to have the form and in the cod footer they're going to have the links. Footer. Oh, game. Same is going to be for their grade for the new action. I mean, so we have a new course and they're going to make it as for the new enrolment, they're coping the title. We're going to add new enrollment. And here we are going to create a cold. So FA, lock open new enrollment called body, where we're going to put our form and got foot arrival will put the links. Let's see how it looks. They're going to enrollments and new enrollment looks quite nice. Now let's make it look nice. So they're going to enrollments and in the price we're going to add the number to currency method and gentleman price. Okay? And it will make the code look a bit better. Also, I'm in the table. So table. Let's see. Now they're adding some Bootstrap classes. Table bordered, table-striped. They're going to make the stable more compact. So we're going to make the table as M method. Okay? And here's our user's table. Here is our gentleman stable. Now you see that if we make our screen smaller and moved to the side and our table isn't responsive and it's moving out to the side to make it work properly. They're going to do at the table responsive class above the table. And they're going to nest the table inside this class. So they are going to refresh now. And we see that now we have a scroll bar inside the table and our homepage isn't moving. Let's see our users, but we are also using a table. And we're going to add the same table clauses for it. Now we're going to nest the content inside. And in dental have a break. Okay? So they're going to our users. Here is our table. And we said that we have a scroll bar. And let's just remove the search fields that found going to use in uses