2.4 Adding Comments: Part 1
Let’s continue to add to the feature set of our project management app. In this lesson, we’ll add comments to tasks. This will be a slightly more complex situation, because we’ll have to modify the results of the generator in order to reflect our desired functionality.
1.Introduction2 lessons, 14:01
2.Building a Rails Application11 lessons, 2:09:35
3.Conclusion1 lesson, 02:23
2.4 Adding Comments: Part 1
The previous lesson was a little theoretical. I've introduced you to the topic of validations. I thought it was necessary for you to learn about it in the way that I've showed you. Now in this lesson, we're going to dive deep in to the code again. We're actually going to create a new model, and with that we'll create a new mechanism to add in more value to our application. We're going to add comments to the tasks. So without further adieu, let's go to the terminal and invoke another generator. I'll call the rails generate command. Actually, now that I think of it, g is a shorthand available for generate. So rails g, and instead of using the scaffold generator, I'll use the model one. And like the scaffold generator, the model one only generates the model, unlike the scaffold, which generates a whole system for creating, updating, and listing a particular resource. So model it is. Now we need to specify the name of our model. I'm going to call it comment. Now the comment needs some data, some attributes. I'll create a name variable which will hold whoever's commenting on the task. Then, for example, the email, I guess that's also a possibility, and a body of text. So I'll use the text after the colon to specify that this body attribute will be a large text. If we press Enter now, we will see a bunch of different files created. However, it is really small now. We only have a couple of them. Namely, the migration is the first one, then the model, and then some files for testing. Now let's go ahead and open our editor and see the new files. I'm going to go to db, migrate, and then let's see, create comments. The comments table will have a name, a string, and a body. I'm going to take the chance and pass in here null false. Also, the same in the body and the email. The reason I'm doing this is because I don't want the comments to be without name or email or a body. This is an option that's available in the mechanism of migrations. Check the link in the description below to learn a little bit more about migrations and their options. Okay, with this I can go back to the terminal and type in the rake db migrate command as you're used to. This will migrate the database in order to include one more change, in this case the comments table. Now that's taken care of we can focus our attention on actually providing a form, for example, to create a new comment. Lets go to app then models and then comment. This is actually a great opportunity to show something that I've totally missed. I'm going to go to that db migrate folder again and reach to the create comments task. You can see here that there's no relationship between the comments and the task, and we need it. So instead of this, I'm going to add in a t.references and then task. This new instruction is very similar to the task one. In fact, I'm going to go to db > migrate > create tasks. As you can see, we have that very same reference, but instead of the project, I should have task. Also I should make sure that these two options are also there. Create an index and a foreign key to this specific attribute so that we get a boosting performance. So back to the references method here. I'm going to add in those new options and there you go. Now you might be thinking that we already ran this migration. We're introducing a new change to it, how do we rerun this migration? Well, that's easy. With every change in the migration it is possible to revert it. So instead of break db migrate, i use break db rollback. Use the rollback command to drop that table. Then, just run the migrate command again and you get that same table with the new change. Awesome, now as far as the comment model goes, we need to establish this relationship. Belongs_to :task allows us to relate the task with a comment. Now, in the test model we also need to add in one more relationship and that is has_many :comments. Okay, the same way as we did with the project in which it has many tasks, we use the same mechanism to relate the task to the comments. Remember you need to establish the relationship in both files so that you can access one from the other. Okay, I guess that's it in regards to the models, but how do we go from the browser? Let's actually take the chance to go there. So I'm just going to restore the projects window. There you go. So let's go to this project. Oh, it seems that there are no tasks here, so I'm going to go to the first one. And going to this task, I wish there was something here that would list all of my comments and give me the chance to create another one. This is a great opportunity to demonstrate how you can do something manually without resorting to the generators, so we'll go from there. In the views, I'm going to go to tasks and then /show.html.erb. Basically, I want to have a header here, so comments. I want to introduce the comments for this task, so from here we can create for example an order list and loop through all of the tasks comments. So @task.comments.each will pass in a comment and close the block like so. Remember this is basically Ruby code. So we just use an each method to all of the comments and then we close the block with an end. Now from here I can just type in a list item with some data, namely the name, the email if we do want to, and then the body of text. Let's say a header here with the comment's name, and then the body. I'm going to use block quote and from here, the comment's body. I think that's good. Next we want to allow the possibility of entering a new comment. So I'm going to utilize a helper method that will allow me to create a form. I'll use the form_for method, and then I'll pass in an array. At the end of the method, I'll pass in a block that gets a form builder. The form builder with the value of F is a special object that contains HTML form element functions. Let's continue on so I can explain to you what we can do with it. The reason I'm placing an array, and like other forms that we handled before. For example the form for the task only gets the task. As I've mentioned before, Rails makes it very easy to relate the models with the respective resource routes. However, we're going to make it so that in the form for here we'll pass in the task and then a task.comments.build. This will build a new comment object and because we have an array with task and a comment, we should get a different route. Remember, the array with these two elements will generate a route for us. Now, let me just try and hit save right now and reload the page to see what error we should be facing, because most definitely we will face an error. So reloading the page you can see that the message we get is, undefined method task_comments_path. Okay. This means that we need to have some kind of a route that will support this name. Let's pick up on rake routes. This is the entire list of URLs that the application can feed. We're still missing something about the comments. We only have projects and task related routes. Let's go to config/routes. We're going to open it in a tab. And from this particular setting, you can see we have the resources for the tasks, and the resources for the projects. I will pass a block to resources tasks. And type in resources :comments. This will change the scenario dramatically. If I go ahead and show you the routes again, we will see a much different perspective. The task_comments path is right there. The post route. It will go to comments/create. So the create action will be there. We will need a comments controller, of course, so that we can introduce a new comment. Now, I'm going to actually introduce a new option in this resources method and I'm only going to show the create action. Basically, from all the possible methods available in the resources method, I just wanna have the create route. When I do this, you will see that the only route around the comments is this one, and that's it. That way, we won't need to implement every single action and the comments controller. Okay. Now, let's go ahead and reload this page because this will no longer present an error. If I go ahead and inspect the elements of the page, so let's go to body there's our form. It has nothing in it aside from some values. Important ones for authentication and security, but still we have this /tasks/1/comments. So we want to create a comment that's related to this task. That's exactly what it means. We'll continue developing this form in part two. Jump right in.