Louis93
Louis93

Reputation: 3913

No route matches - missing required keys: [id] ?

I'm doing a Rails tutorial, and trying to figure out why this is happening.

I'm making a to-do list, and everytime I try and insert a record into my Todo model, I get the following:

error!

Here is the new.html.erb view that this is from:

<h1>Add new item to your todo listM</h1>
<%= form_for @todo, :url=>todo_path(@todo) do |f| %>
    <%= f.label :name %> <%= f.text_field :name%>
    <%= f.hidden_field :done, :value => false %>
    <%= f.submit "Add to todo list" %>
<% end %>

Here is index.html.erb from where the user is linked to new.html.erb

<h1>TASKS</h1>

<h3> TO DO </h3>
<ul>
<% @todos.each do |t| %>
    <li>
        <strong><%= t.name %></strong>
        <small><%= link_to "Mark as Done", todo_path(t), :method => :put %></small>
    </li>
<% end %>
</ul>

<h3> DONE </h3>
<ul>
<% @todones.each do |t| %>
    <li>
        <strong><%= t.name %></strong>
        <small><%= link_to "Remove", t, :confirm => "You sure?", :method => :delete %></small>
    </li>
<% end %>
</ul>

<%= link_to "Add new task", new_todo_path %>

Here is the TodoController I have managing these actions:

class TodoController < ApplicationController

    def index
        @todos = Todo.where(done:false)
        @todones = Todo.where(done:true)
    end

    def new
        @todo = Todo.new
    end

    def todo_params
        params.require(:todo).permit(:name, :done)
    end

    def create
        @todo = Todo.new(todo_params)
        if @todo.save
            redirect_to todo_index_path, :notice => "Your todo item was created!"
        else
            render "new"
        end
    end

    def update
        @todo = Todo.find(params[:id])

        if @todo.update_attribute(:done, true)
            redirect_to todo_index_path, :notice => "Your todo item was marked done!"
        else
            redirect_to todo_index_path, :notice => "Couldn't update your task"
        end
    end

    def destroy
        @todo = Todo.find(params[:id])
        @todo.destroy

        redirect_to todo_index_path, :notice => "Your todo item was deleted"
    end

end

And finally the routes.rb

Oneday::Application.routes.draw do
  devise_for :users
  root 'home#index'
  resources :todo
end

Any input as to why this is happening and how to rectify it would be great.

Upvotes: 1

Views: 6737

Answers (3)

abeltensor
abeltensor

Reputation: 13

I found a fix to this exact issue if anyone is still curious, i know its an old issue and an easy one at that, but still figured id solve it. the original route todo_path leads to todo#show. todo_index however is assigned to todo#index and todo#create so its what we want. the line should look like this:

<%= form_for @todo, :url => todo_index_url(@todo), method: :post do |f| %>

I encountered a similar issue with one of my applications and stumbled across this post as a fix. None of the suggestions worked for me, but i was able to fix it with a little tinkering on the routes.

Upvotes: 0

Vitalyp
Vitalyp

Reputation: 1089

You do not comply with the rails convention. Use plural form for resources. Then, your action is correct.

  • TodosController, todos_controller.rb, resources :todos

( Rails use singular/plural format to support RESTful links and to recognize named actions )

Upvotes: 4

zwippie
zwippie

Reputation: 15515

This

<%= form_for @todo, :url=>todo_path(@todo) do |f| %>

will set (or leave) the form http method to get. You could change it to:

<%= form_for @todo, :url=>todo_path(@todo), method: :post do |f| %>

or even shorter, leave it to Rails to find out what method is needed:

<%= form_for @todo do |f| %>

Upvotes: 0

Related Questions