Welcome back! In the previous lessons, you learned how to retrieve and create ToDo
items. Now, it's time to make our application even more powerful by adding the ability to update and delete ToDo
items. These actions are crucial because they allow users to manage their tasks dynamically, keeping their to-do list accurate and up-to-date.
In this lesson, you will:
- Add functionality to update an existing
ToDo
item. - Implement the ability to delete
ToDo
items.
Both of these features are critical for a fully functional ToDo
application. Imagine having a list that you can't edit or update — you would soon find it outdated and not very useful.
Let's first look at how to add the update feature. Open your todos_controller.rb
and add the following methods:
Ruby1class TodosController < ApplicationController 2 def edit 3 @todo = TodoService.get_by_id(params[:id]) 4 end 5 6 def update 7 todo = TodoService.update(params[:id], todo_params) 8 if todo 9 redirect_to todo_path(todo[:id]) 10 else 11 render :edit, status: :unprocessable_entity 12 end 13 end 14 15 private 16 17 def todo_params 18 params.require(:todo).permit(:title, :description) 19 end 20end
Additionally, update the TodoService
to include the update
method:
Ruby1class TodoService 2 # Existing methods... 3 4 def self.update(id, params) 5 todo = Todo.find_by(id: id) 6 return false unless todo 7 8 if todo.update(params) 9 todo 10 else 11 false 12 end 13 end 14end
Explanation:
-
edit
method: This method retrieves theToDo
item that needs to be edited. It does so by callingTodoService.get_by_id
, passing in theid
from the parameters, and assigns it to the instance variable@todo
. -
update
method: This method updates theToDo
item. It callsTodoService.update
, providing theid
and the permitted parameters fromtodo_params
. If the update is successful (todo
is truthy), it redirects to the show page of the updatedToDo
. If the update fails, it re-renders the edit form, returning anunprocessable_entity
status. -
todo_params
method: This private method uses strong parameters to control which attributes can be updated. It requires the parameters to have atodo
object and permits only thetitle
anddescription
attributes. -
TodoService.update
method: Finds aToDo
item by itsid
and updates it with the provided parameters. It returns the updatedtodo
object if successful, otherwisefalse
.
In the form view (app/views/todos/edit.html.erb
), we'll create a form for users to edit their existing ToDo
items:
ERB1<h1>Edit Todo</h1> 2<%= form_with scope: :todo, url: todo_path(@todo[:id]), method: :put, local: true do |form| %> 3 <div> 4 <%= form.label :title %> 5 <%= form.text_field :title, value: @todo[:title] %> 6 </div> 7 <div> 8 <%= form.label :description %> 9 <%= form.text_area :description, value: @todo[:description] %> 10 </div> 11 <div> 12 <%= form.submit "Update" %> 13 </div> 14<% end %> 15<%= link_to 'Delete', todo_path(@todo[:id]), method: :delete, data: { confirm: 'Are you sure?' } %>
Explanation:
-
form_with
: Generates a form for theToDo
item usingform_with
. It sets the method toput
to represent an update action and scopes it to thetodo
object. -
Form elements: The form contains a labeled text field for the
title
and a text area for thedescription
, pre-filled with the current values using@todo
. -
Submit button: The form includes a submit button labeled "Update" that will send the updated data when clicked.
-
Delete link: A link is provided to allow users to delete the
ToDo
item directly from the edit page, with a JavaScript confirmation dialog.
Deleting a ToDo
item is just as important as creating or updating one. Here's how you can enable users to remove tasks that are no longer needed. Add the destroy
method to your todos_controller.rb
:
Ruby1class TodosController < ApplicationController 2 def index; @todos = TodoService.get_all; end 3 4 def show; @todo = TodoService.get_by_id(params[:id]); end 5 6 def edit; @todo = TodoService.get_by_id(params[:id]); end 7 8 def update 9 todo = TodoService.update(params[:id], todo_params) 10 redirect_to todo ? todo_path(todo[:id]) : :edit, status: todo ? :ok : :unprocessable_entity 11 end 12 13 def destroy 14 TodoService.delete(params[:id]) 15 redirect_to todos_path 16 end 17 18 private 19 20 def todo_params 21 params.require(:todo).permit(:title, :description) 22 end 23end
Add the delete
method to the TodoService
:
Ruby1class TodoService 2 # Existing methods... 3 4 def self.delete(id) 5 todo = Todo.find_by(id: id) 6 todo&.destroy 7 end 8end
Explanation:
-
destroy
method in the controller: This method deletes the specifiedToDo
item by callingTodoService.delete
with the appropriateid
. After deletion, it redirects to the list of allToDos
(todos_path
). -
TodoService.delete
method: This method retrieves theToDo
item by itsid
and deletes it using thedestroy
method if it exists. The safe navigation operator&
is used to ensure thatdestroy
is called only iftodo
is notnil
.
Updating and deleting ToDo
items are essential features for any task management application. They provide users with the flexibility to keep their task list current, efficient, and relevant. The ability to modify and clean up a to-do list is what makes an application truly dynamic and user-friendly.
By the end of this lesson, you will have empowered users to interact more meaningfully with your app, making it a valuable tool for everyday task management. Exciting, isn't it? Let's jump into the practice section and bring these features to life!