Yoklan
Yoklan

Reputation: 211

Update an attribute via a link_to from within a loop, can't pass ID

I'm trying to change the value of completed, which is a boolean from the default false to true using the update method in the controller. I'm trying to make it so that I can display all of the task_items and a link next to them to change the value. This is what I got:

TaskItem is nested in TaskList

<% @task_list.task_items.each do |task_item| %>
  <%= task_item.content %>
  <%= link_to "Complete", task_list_task_item_path(task_list_id: @task_list.id, :task_item => {:completed => true} ), :method => :patch %>
<% end %>

I'm getting no route matches missing required keys [:id] error.

Routes

  concern :has_task_lists do
    resources :task_lists, only: [:new, :index, :create, :show]
  end

  resources :events, :meetings, concerns: [:has_task_lists]

  resources :task_lists, except: [:new, :index, :create] do
    resources :task_items  
  end

Controller

class TaskItemsController < ApplicationController
    before_action :set_task_list

    def index
        @task_items = @task_list.task_items
    end

    def new
    @task_item = @task_list.task_items.new
  end

    def create
      @task_item = @task_list.task_items.new(task_item_params)
      if @task_item.save
        redirect_to :back
      else
        render :new
      end
  end

    def show
        @task_item = @task_list.task_items.find(params[:id])
  end

    def update
    @task_item = @task_list.task_items.find(params[:id])
    if @task_item.update_attributes(task_item_params)
      redirect_to :back, notice: "Task Item Updated"
    else
      render :edit
    end
  end

  def edit
    @task_item = @task_list.task_items.find(params[:id])
  end

    private

    def task_item_params
        params.require(:task_item).permit(:content, :completed)
    end

    def set_task_list
    @task_list = TaskList.find(params[:task_list_id])
  end

end

Upvotes: 0

Views: 74

Answers (3)

Yoklan
Yoklan

Reputation: 211

I've solved my issue.

I created a new method instead of using the update and added a custom route to it. Also deleted some controller methods that were of no use to me. Here is the code that worked for me for anyone who might have a similar issue.

class TaskItemsController < ApplicationController

    Omitted Index, Create, etc.

    def complete
      @task_item = @task_list.task_items.find(params[:task_item_id])
      @task_item.completed = true
      if @task_item.save
        redirect_to :back
      end
    end

end

  resources :task_lists  do
    resources :task_items, only: [:new, :index, :create] do
      member do
        patch 'complete'
      end
    end
  end

<% @task_list.task_items.each do |task_item| %>
  <%= task_item.content %>
  <% if task_item.completed == false %>
    <%= link_to "Complete", complete_task_list_task_item_path(:task_list_id => @task_list.id, :task_item_id => task_item.id), method: :patch %> <br />
  <% end %>
<% end %>

Upvotes: 0

Chung Phước
Chung Phước

Reputation: 19

The link should be:

<%= link_to "Complete", task_list_task_item_path(@task_list, task_item, completed: true), method: :patch %>

And make sure that you have require jquery and jquery_ujs in application.js file. Because I did meet problem when use link_to with method delete, patch when I remove require jquery_ujs from the application.js

Upvotes: 0

SteveTurczyn
SteveTurczyn

Reputation: 36880

You're not passing the task_item to the link_to... how is it supposed to know which task item to update?

Better might be...

 <%= link_to "Complete", task_list_task_item_path(@task_list, task_item, :completed => true), :method => :patch %>

Upvotes: 1

Related Questions