My Rails 7 app uses the following models:
Batch
model,has_many
tasksTask
model,belongs_to
a batch
Resources are nested as follows:
resources :batches do
resources :tasks
end
The Task model has a completed_at
field, which is nil
by default, and which we want to update to DateTime.now
when the task is completed.
The goal is to display tasks in the task index view, with a do/undo button depending on whether the task has already been completed or not (a task can be completed, and then uncompleted, and in that case we want to reset the value of completed_at
to nil
).
To determine whether a task has been completed, the following method has been added to the Task model:
def completed?
!completed_at.nil?
end
In the task index view, tasks are displayed as follows:
<% @tasks.each do |task| %>
<li>
<div>
<%= do_or_undo(@batch, task) %>
<%= task.title %>
</div>
</li>
<% end %>
The do_or_undo(batch, task) method is defined as a task view helper in tasks_helper.rb
, as follows:
def do_or_undo(batch, task)
unless task.completed?
button_to "Do", batch_task_path(batch, task), data: { turbo_method: :update }
else
button_to "Undo", batch_task_path(batch, task), data: { turbo_method: :update }
end
end
In the tasks index view, the correct variation of the do or undo button is display when first loading the view, however, when clicking on that button, the value of the completed_at
field is not updated, neither to nil
when clicking on undo, nor to DateTime.now
when clicking on do — and the text of the button is not updated (neither to do when clicking undo, nor to undo when clicking do).
No error is being thrown, which is the reason why I am unsure where to go next to investigate and fix the issue.
Two questions:
- Why is this not working?
- Is there a better way to implement this, maybe with a checkbox instead of a button (using jQuery or Hotwire)?
CodePudding user response:
The problem here is the turbo_method attribute this has to be one of
get, post, put, delete
link_to "Update", your_url, data: { turbo_method: :put }
for your case you should use the put method in your link if you want to make a request to the update action. Then inside of the controller action you will want to redirect the user to update the page or respond with a turbo_stream to do so