Rails: No route matches ... missing required keys: [:id]

16,024

Solution 1

The reason for this is that you are passing an unsaved instanced of 'reminder' into the edit_reminder_path. When you pass an instance as a parameter to a route the 'to_param' method is called on that instance. By default the 'to_param' method returns the 'id' of the instance.

In your case you have:

def index
  @reminders = current_user.reminders
  @reminder = current_user.reminders.new
end

Because you have scoped the @reminder to the current user. That instance is added to the collection of reminders for that user, and so is also included in @reminders. This means that when you are rendering out the @reminders on the index page, It also tries to render out the unsaved @reminder which has not yet got an 'id' set.

A better solution would be to change you index action to:

def index
  @reminders = current_user.reminders
  @reminder = Reminder.new
end

And then at the point that you save the reminder, most likely in a 'create' action, you would scope to the current_user:

def create
  @reminder = current_user.reminders.new(reminder_params)
  if @reminder.save .....
end

Solution 2

The error is in your index action:

def index
  @reminders = current_user.reminders
  @reminder = current_user.reminders.new # <== HERE
end

You're adding a new unpersisted instance to the current_user.reminders collection, which is what this error is telling you when you iterate that collection and try to link_to that one: No route matches {:id=>#<Reminder id: nil

Share:
16,024
JeremyE
Author by

JeremyE

Creator of JointsWP.com.

Updated on June 05, 2022

Comments

  • JeremyE
    JeremyE almost 2 years

    Full error:

    No route matches {:id=>#<Reminder id: nil, medication: nil, time: nil, created_at: nil, updated_at: nil, user_id: 1>} missing required keys: [:id]
    

    Here is the code from index.html.erb that is causing the error:

    <tbody>
        <% @reminders.each do |reminder| %>
          <tr <%= dom_id(reminder) %>>
            <td><%= reminder.medication %></td>
            <td><%= reminder.time %></td>
            <td>
              <%= link_to "Edit", edit_reminder_path(reminder) %>
              or
              <%= link_to 'Remove', reminder, method: :delete, data: { confirm: 'Are you sure?' } %>
          </td>
          </tr>
        <% end %>
      </tbody>
    

    Models:

    class Reminder < ActiveRecord::Base
        validates :medication, presence: true
        belongs_to :user
    end
    class User < ActiveRecord::Base
      has_many :reminders
    end
    

    Actions:

      def index
        @reminders = current_user.reminders
        @reminder = current_user.reminders.new 
      end
      def edit
      end
    

    Routes:

    Medy::Application.routes.draw do
      devise_for :users
      resources :reminders
      root 'reminders#index'
    end
    

    Do I need to add something to the edit action to make this work?

    The error started happening after I changed @reminders = Reminders.all to @reminders = current_user.reminders in the index action.