I have a projects model that has many tasks. You can click a checkbox to complete the task and what I am trying to have happen is when that happens change the style of the task and return some additional information. The task updates fine and completes, but errors out on the form and checkbox stating "Nil location provided. Can't build URI " when trying to return the turbo stream. Also when creating new tasks I get the same error. Any thoughts on why in both cases it is triggering that error?
Task.html.erb:
<div class="table-row" id="<%= dom_id task %>" data-id="<%= task.id %>">
<div class="table-cell px-6 py-4 whitespace-nowrap text-md font-medium text-gray-800 dark:text-gray-200"><%= form_with(model: [@project, @task]) do |form| %><%= form.check_box :completed,
data: {
id: task.id,
action: "tasks#toggle"
},checked: task.completed,
class: "w-4 h-4 border-gray-300 rounded bg-gray-50 focus:ring-3 focus:ring-primary-300 dark:focus:ring-primary-600 dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600" %><% end %>
</div>
<div class="table-cell px-6 py-4 whitespace-nowrap text-md text-gray-800 dark:text-gray-200">
<div class="text-base font-semibold text-gray-900 dark:text-white"><%= task.description %>
</div>
<div class="text-sm font-normal text-gray-500 dark:text-gray-400"><% if task.completed? %>
<div class="text-base font-normal text-gray-500 dark:text-gray-400">Completed: <%= time_ago_in_words(task.updated_at) %> ago
</span> by
<span class="font-weight-normal ml-2"><%= task.user.email %>
</div><% end %>
</div>
</div>
<div class="table-cell px-6 py-4 whitespace-nowrap text-right text-md font-medium">
<div class="flex justify-end">
<button type="button" data-modal-toggle="product-modal" class="inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-primary-700 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z"></path>
<path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd"></path>
</svg>
Edit item
</button>
<button type="button" data-modal-toggle="delete-product-modal" class="inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-red-700 rounded-lg hover:bg-red-800 focus:ring-4 focus:ring-red-300 dark:focus:ring-red-900">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd"></path>
</svg>
Delete item
</button>
</div>
</div>
Within project/show:
<%= turbo_stream_from "tasks" %>
<div class="overflow-hidden">
<div class="table border-collapse table-auto w-full divide-y divide-gray-200 dark:divide-gray-700">
<div class="table-row-group divide-y divide-gray-200 bg-white dark:divide-gray-700 dark:bg-gray-800"
id="tasks" data-controller="drag" data-drag-url="/projects/<%= @project.id %>/tasks/:id/move">
<%= render @tasks.order('position asc') %>
</div>
</div>
</div>
Task.rb
class Task < ApplicationRecord
belongs_to :project
belongs_to :user
acts_as_list
after_create_commit {broadcast_prepend_to "tasks"}
end
Tasks controller:
class TasksController < ApplicationController
before_action :set_task, except: [:create]
before_action :set_project, except: [:toggle]
# GET /tasks or /tasks.json
def index
@tasks = Task.all
@task = Task.new
end
# GET /tasks/1 or /tasks/1.json
def show
end
# GET /tasks/new
def new
@task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks or /tasks.json
def create
@task = @project.tasks.build(task_params)
@task.user_id = current_user.id
respond_to do |format|
if @task.save
format.turbo_stream
format.html { redirect_to project_task_path(@project, @task), notice: "Task was successfully created." }
format.json { render :show, status: :created, location: @task }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1 or /tasks/1.json
def update
respond_to do |format|
if @task.update(task_params)
format.html { redirect_to project_task_path(@project, @task), notice: "Task was successfully updated." }
format.json { render :show, status: :ok, location: @task }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1 or /tasks/1.json
def destroy
@task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: "Task was successfully destroyed." }
format.json { head :no_content }
end
end
def toggle
@task = Task.find(params[:id])
@task.update(completed: params[:completed])
end
def move
@task.insert_at(params[:position].to_i)
head :ok
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
@task = Task.find(params[:id])
end
def set_project
@project = Project.find(params[:project_id])
end
# Only allow a list of trusted parameters through.
def task_params
params.require(:task).permit(:title, :position, :description, :project_id, :user_id, :status, :completed)
end
end