- Read Tutorial
- Watch Guide Video
In this lesson, we are going to learn to do conditional callbacks for our task
model. What this callback is going to do is it will look at the task
every time it is saved, and if it is marked complete
, the callback will increase the count of the parameter percent_complete
of the project
that the task
belongs to.
To do this, go to the task.rb
file and type the code
after_save :update_percent_complete if :mark_completed?
This callback after_save
will be called when a task is created and it is marked as complete. It will also be called when a task is updated and marked as complete.
Next, we are going to create two methods called mark_completed?
and update_percent_complete
.
Now, what this code will do is it will run the method update_percent_complete
if the mark_completed
method returns a true value. In Ruby, a method will come back as true if the value is not nil
and not false
.
Inside the mark_completed
method, type this code:
self.completed == true
What this means is if the completed
parameter of that particular instance of Task
is true
, then the method will return a true
value. On the other hand, if this parameter does not have the value true
, then the method will return false and nothing else will happen.
Next, let's create our update_percent_complete
method:
def update_percent_complete project = Project. find(self.project_id) count_of_completed_tasks = project.tasks.completed.count count_of_total_tasks = project.tasks.count project.update!(percent_complete: Counter.calculate_percent_complete(count_of_completed_tasks, count_of_total_tasks)) end
In this method, in the first line, we are going to find the project with the project_id
of that particular instance of task
. This project is stored in a local variable called project
.
In the second line, we are going to create a variable count_of_completed_tasks
, and in this variable, we are putting the count of tasks that are marked as complete in that project. Now, we want the code to know what is completed
, and for this we create a scope to the model:
scope :completed, -> {where ('completed: true')}
This scope tells the second line of code that completed
means any task with a parameter of completed
is marked as true.
In the third line, we create another variable called count_of_total_tasks
and here we store the count of all the tasks in the project.
In the fourth line, we want to update the percent_complete
parameter of our project
record. To calculate what the value of percent_complete
we are going to use the Counter
class that we created a few lessons back. If you remember, this class has a method called calculate_percent_complete
that takes two parameters. So, we invoke this method here with count_of_completed_tasks
and count_of_total_tasks
as its parameters.
Now, we can test it on our console. Start the console with the command rails c
Next, let's store the last project in a variable with the command
p = Project.last
This means the p
variable will now have the value of the last project
that has a project_id
of 21
. Let's now check if this project
has any tasks with the command p.tasks
This returns two tasks for us. If you want to see the percent_complete
value, type:
p.percent_complete.to_s
In this command, we are converting the value of "percent_complete" to a string value because it can be quite long otherwise. This value is currently 0.0
Next, let's see the completed
value of the last task with the command Task.last
. If you see, this command brings up the last task whose completed value is nil. Next, we update the completed value of this task with the command:
Task.last.update!(completed:true)
Now that the completed value has been changed to true for the task's record in the project with an id of 21
, we can check the if the percent_complete
is updated with the command:
Project.last.percent_complete.to_s
This returns a value of 50.0
, which means, our code worked perfectly!
You can see all these commands below.
Next, we can check if the update function works by changing the value of completed
to false again with the command:
Task.last.update!(completed: false)
After this is executed, next check the value of percent_complete
with the command:
Project.last.percent_complete.to_s
and this returns a value of 0.0
again, which is what we want.
We were able to do all of this because tasks and projects are connected to each other.